DCE-driven mode
:js:js.tests:jsIrTest works same as before :js:js.tests:jsPirTest runs tests in DCE-driven mode
This commit is contained in:
@@ -18,6 +18,7 @@ workspace.xml
|
|||||||
/jps-plugin/testData/kannotator
|
/jps-plugin/testData/kannotator
|
||||||
/js/js.translator/testData/out/
|
/js/js.translator/testData/out/
|
||||||
/js/js.translator/testData/out-min/
|
/js/js.translator/testData/out-min/
|
||||||
|
/js/js.translator/testData/out-pir/
|
||||||
.gradle/
|
.gradle/
|
||||||
build/
|
build/
|
||||||
!**/src/**/build
|
!**/src/**/build
|
||||||
|
|||||||
+3
@@ -125,6 +125,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
|
|||||||
@Argument(value = "-Xir-dce", description = "Perform experimental dead code elimination")
|
@Argument(value = "-Xir-dce", description = "Perform experimental dead code elimination")
|
||||||
var irDce: Boolean by FreezableVar(false)
|
var irDce: Boolean by FreezableVar(false)
|
||||||
|
|
||||||
|
@Argument(value = "-Xir-dce-driven", description = "Perform a more experimental faster dead code elimination")
|
||||||
|
var irDceDriven: Boolean by FreezableVar(false)
|
||||||
|
|
||||||
@Argument(value = "-Xir-only", description = "Disables pre-IR backend")
|
@Argument(value = "-Xir-only", description = "Disables pre-IR backend")
|
||||||
var irOnly: Boolean by FreezableVar(false)
|
var irOnly: Boolean by FreezableVar(false)
|
||||||
|
|
||||||
|
|||||||
@@ -228,13 +228,14 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
friendDependencies = friendDependencies,
|
friendDependencies = friendDependencies,
|
||||||
mainArguments = mainCallArguments,
|
mainArguments = mainCallArguments,
|
||||||
generateFullJs = !arguments.irDce,
|
generateFullJs = !arguments.irDce,
|
||||||
generateDceJs = arguments.irDce
|
generateDceJs = arguments.irDce,
|
||||||
|
dceDriven = arguments.irDceDriven
|
||||||
)
|
)
|
||||||
} catch (e: JsIrCompilationError) {
|
} catch (e: JsIrCompilationError) {
|
||||||
return COMPILATION_ERROR
|
return COMPILATION_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsCode = if (arguments.irDce) compiledModule.dceJsCode!! else compiledModule.jsCode!!
|
val jsCode = if (arguments.irDce && !arguments.irDceDriven) compiledModule.dceJsCode!! else compiledModule.jsCode!!
|
||||||
outputFile.writeText(jsCode)
|
outputFile.writeText(jsCode)
|
||||||
if (arguments.generateDts) {
|
if (arguments.generateDts) {
|
||||||
val dtsFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "d.ts")!!
|
val dtsFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "d.ts")!!
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.Ir
|
import org.jetbrains.kotlin.backend.common.ir.Ir
|
||||||
import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager
|
import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
@@ -35,4 +36,5 @@ interface BackendContext {
|
|||||||
val internalPackageFqn: FqName
|
val internalPackageFqn: FqName
|
||||||
val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
|
val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
|
||||||
val lateinitNullableFields: MutableMap<IrField, IrField>
|
val lateinitNullableFields: MutableMap<IrField, IrField>
|
||||||
|
val extractedLocalClasses: MutableSet<IrClass>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ open class DefaultMapping : Mapping {
|
|||||||
override val lateInitFieldToNullableField: Mapping.Delegate<IrField, IrField> = newMapping()
|
override val lateInitFieldToNullableField: Mapping.Delegate<IrField, IrField> = newMapping()
|
||||||
override val inlineClassMemberToStatic: Mapping.Delegate<IrFunction, IrSimpleFunction> = newMapping()
|
override val inlineClassMemberToStatic: Mapping.Delegate<IrFunction, IrSimpleFunction> = newMapping()
|
||||||
|
|
||||||
protected fun <K : IrDeclaration, V> newMapping() = object : Mapping.Delegate<K, V>() {
|
protected open fun <K : IrDeclaration, V> newMapping() = object : Mapping.Delegate<K, V>() {
|
||||||
private val map: MutableMap<K, V> = mutableMapOf()
|
private val map: MutableMap<K, V> = mutableMapOf()
|
||||||
|
|
||||||
override operator fun get(key: K): V? {
|
override operator fun get(key: K): V? {
|
||||||
|
|||||||
+1
@@ -44,6 +44,7 @@ open class LocalClassPopupLowering(val context: BackendContext) : BodyLoweringPa
|
|||||||
|
|
||||||
for ((local, newContainer) in extractedLocalClasses) {
|
for ((local, newContainer) in extractedLocalClasses) {
|
||||||
newContainer.addChild(local)
|
newContainer.addChild(local)
|
||||||
|
context.extractedLocalClasses += local
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,11 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js
|
package org.jetbrains.kotlin.ir.backend.js
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsName
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsName
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
@@ -28,11 +25,13 @@ fun eliminateDeadDeclarations(
|
|||||||
mainFunction: IrSimpleFunction?
|
mainFunction: IrSimpleFunction?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val allRoots = buildRoots(module, context, mainFunction)
|
val allRoots = stageController.withInitialIr { buildRoots(module, context, mainFunction) }
|
||||||
|
|
||||||
val usefulDeclarations = usefulDeclarations(allRoots, context)
|
val usefulDeclarations = usefulDeclarations(allRoots, context)
|
||||||
|
|
||||||
removeUselessDeclarations(module, usefulDeclarations)
|
stageController.unrestrictDeclarationListsAccess {
|
||||||
|
removeUselessDeclarations(module, usefulDeclarations)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrField.isConstant(): Boolean {
|
private fun IrField.isConstant(): Boolean {
|
||||||
@@ -42,13 +41,14 @@ private fun IrField.isConstant(): Boolean {
|
|||||||
private fun buildRoots(module: IrModuleFragment, context: JsIrBackendContext, mainFunction: IrSimpleFunction?): Iterable<IrDeclaration> {
|
private fun buildRoots(module: IrModuleFragment, context: JsIrBackendContext, mainFunction: IrSimpleFunction?): Iterable<IrDeclaration> {
|
||||||
val rootDeclarations =
|
val rootDeclarations =
|
||||||
(module.files + context.packageLevelJsModules + context.externalPackageFragment.values).flatMapTo(mutableListOf()) { file ->
|
(module.files + context.packageLevelJsModules + context.externalPackageFragment.values).flatMapTo(mutableListOf()) { file ->
|
||||||
file.declarations.filter {
|
file.declarations.flatMap { if (it is IrProperty) listOfNotNull(it.backingField, it.getter, it.setter) else listOf(it) }
|
||||||
it is IrField && it.initializer != null && it.fqNameWhenAvailable?.asString()?.startsWith("kotlin") != true
|
.filter {
|
||||||
|| it.isExported(context)
|
it is IrField && it.initializer != null && it.fqNameWhenAvailable?.asString()?.startsWith("kotlin") != true
|
||||||
|| it.isEffectivelyExternal()
|
|| it.isExported(context)
|
||||||
|| it is IrField && it.correspondingPropertySymbol?.owner?.isExported(context) == true
|
|| it.isEffectivelyExternal()
|
||||||
|| it is IrSimpleFunction && it.correspondingPropertySymbol?.owner?.isExported(context) == true
|
|| it is IrField && it.correspondingPropertySymbol?.owner?.isExported(context) == true
|
||||||
}.filter { !(it is IrField && it.isConstant() && !it.isExported(context)) }
|
|| it is IrSimpleFunction && it.correspondingPropertySymbol?.owner?.isExported(context) == true
|
||||||
|
}.filter { !(it is IrField && it.isConstant() && !it.isExported(context)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.hasTests) rootDeclarations += context.testContainer
|
if (context.hasTests) rootDeclarations += context.testContainer
|
||||||
@@ -121,14 +121,16 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendConte
|
|||||||
val constructedClasses = hashSetOf<IrClass>()
|
val constructedClasses = hashSetOf<IrClass>()
|
||||||
|
|
||||||
fun IrDeclaration.enqueue() {
|
fun IrDeclaration.enqueue() {
|
||||||
if (this !in result) {
|
if ((this !is IrProperty || this.isExternal) && this !in result) {
|
||||||
result.add(this)
|
result.add(this)
|
||||||
queue.addLast(this)
|
queue.addLast(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add roots, including nested declarations
|
// Add roots, including nested declarations
|
||||||
roots.withNested().forEach { it.enqueue() }
|
stageController.withInitialIr {
|
||||||
|
roots.withNested().forEach { it.enqueue() }
|
||||||
|
}
|
||||||
|
|
||||||
val toStringMethod =
|
val toStringMethod =
|
||||||
context.irBuiltIns.anyClass.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "toString" }
|
context.irBuiltIns.anyClass.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "toString" }
|
||||||
@@ -141,6 +143,8 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendConte
|
|||||||
while (queue.isNotEmpty()) {
|
while (queue.isNotEmpty()) {
|
||||||
val declaration = queue.pollFirst()
|
val declaration = queue.pollFirst()
|
||||||
|
|
||||||
|
stageController.lazyLower(declaration)
|
||||||
|
|
||||||
if (declaration is IrClass) {
|
if (declaration is IrClass) {
|
||||||
declaration.superTypes.forEach {
|
declaration.superTypes.forEach {
|
||||||
(it.classifierOrNull as? IrClassSymbol)?.owner?.enqueue()
|
(it.classifierOrNull as? IrClassSymbol)?.owner?.enqueue()
|
||||||
@@ -184,6 +188,8 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendConte
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(body as? IrBody)?.let { stageController.lazyLower(it) }
|
||||||
|
|
||||||
body?.acceptVoid(object : IrElementVisitorVoid {
|
body?.acceptVoid(object : IrElementVisitorVoid {
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
@@ -258,7 +264,8 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendConte
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (klass in constructedClasses) {
|
for (klass in constructedClasses) {
|
||||||
for (declaration in klass.declarations) {
|
// TODO a better way to support inverse overrides.
|
||||||
|
for (declaration in ArrayList(klass.declarations)) {
|
||||||
if (declaration in result) continue
|
if (declaration in result) continue
|
||||||
|
|
||||||
if (declaration is IrOverridableDeclaration<*> && declaration.overridesUsefulFunction()) {
|
if (declaration is IrOverridableDeclaration<*> && declaration.overridesUsefulFunction()) {
|
||||||
@@ -277,6 +284,32 @@ fun usefulDeclarations(roots: Iterable<IrDeclaration>, context: JsIrBackendConte
|
|||||||
declaration.enqueue()
|
declaration.enqueue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (declaration in ArrayList(klass.declarations)) {
|
||||||
|
// TODO this is a hack.
|
||||||
|
if (declaration is IrProperty) {
|
||||||
|
declaration.getter?.let { if (it.overridesUsefulFunction()) it.enqueue() }
|
||||||
|
declaration.setter?.let { if (it.overridesUsefulFunction()) it.enqueue() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special hack for `IntrinsicsJs.kt` support
|
||||||
|
if (klass.superTypes.any { it.isSuspendFunctionTypeOrSubtype() }) {
|
||||||
|
ArrayList(klass.declarations).forEach {
|
||||||
|
if (it is IrSimpleFunction && it.name.asString().startsWith("invoke")) {
|
||||||
|
it.enqueue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO find out how `doResume` gets removed
|
||||||
|
if (klass.symbol == context.ir.symbols.coroutineImpl) {
|
||||||
|
ArrayList(klass.declarations).forEach {
|
||||||
|
if (it is IrSimpleFunction && it.name.asString() == "doResume") {
|
||||||
|
it.enqueue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ class JsIrBackendContext(
|
|||||||
override val lateinitNullableFields
|
override val lateinitNullableFields
|
||||||
get() = error("Use Mapping.lateInitFieldToNullableField instead")
|
get() = error("Use Mapping.lateInitFieldToNullableField instead")
|
||||||
|
|
||||||
|
override val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
|
||||||
|
|
||||||
override val builtIns = module.builtIns
|
override val builtIns = module.builtIns
|
||||||
|
|
||||||
override var inVerbosePhase: Boolean = false
|
override var inVerbosePhase: Boolean = false
|
||||||
@@ -57,6 +59,7 @@ class JsIrBackendContext(
|
|||||||
val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false
|
val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false
|
||||||
|
|
||||||
val externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
|
val externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
|
||||||
|
val externalDeclarations = hashSetOf<IrDeclaration>()
|
||||||
val bodilessBuiltInsPackageFragment: IrPackageFragment = run {
|
val bodilessBuiltInsPackageFragment: IrPackageFragment = run {
|
||||||
|
|
||||||
class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSymbol {
|
class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSymbol {
|
||||||
|
|||||||
+144
-71
@@ -55,252 +55,322 @@ private fun makeCustomJsModulePhase(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sealed class Lowering(val name: String) {
|
||||||
|
|
||||||
|
abstract val modulePhase: SameTypeNamedPhaseWrapper<JsIrBackendContext, IrModuleFragment>
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeclarationLowering(
|
||||||
|
name: String,
|
||||||
|
description: String,
|
||||||
|
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||||
|
private val factory: (JsIrBackendContext) -> DeclarationTransformer
|
||||||
|
) : Lowering(name) {
|
||||||
|
fun declarationTransformer(context: JsIrBackendContext): DeclarationTransformer {
|
||||||
|
return factory(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val modulePhase = makeJsModulePhase(factory, name, description, prerequisite)
|
||||||
|
}
|
||||||
|
|
||||||
|
class BodyLowering(
|
||||||
|
name: String,
|
||||||
|
description: String,
|
||||||
|
prerequisite: Set<AnyNamedPhase> = emptySet(),
|
||||||
|
private val factory: (JsIrBackendContext) -> BodyLoweringPass
|
||||||
|
) : Lowering(name) {
|
||||||
|
fun bodyLowering(context: JsIrBackendContext): BodyLoweringPass {
|
||||||
|
return factory(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val modulePhase = makeJsModulePhase(factory, name, description, prerequisite)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModuleLowering(
|
||||||
|
name: String,
|
||||||
|
override val modulePhase: SameTypeNamedPhaseWrapper<JsIrBackendContext, IrModuleFragment>
|
||||||
|
) : Lowering(name)
|
||||||
|
|
||||||
|
private fun makeDeclarationTransformerPhase(
|
||||||
|
lowering: (JsIrBackendContext) -> DeclarationTransformer,
|
||||||
|
name: String,
|
||||||
|
description: String,
|
||||||
|
prerequisite: Set<Lowering> = emptySet()
|
||||||
|
) = DeclarationLowering(name, description, prerequisite.map { it.modulePhase }.toSet(), lowering)
|
||||||
|
|
||||||
|
private fun makeBodyLoweringPhase(
|
||||||
|
lowering: (JsIrBackendContext) -> BodyLoweringPass,
|
||||||
|
name: String,
|
||||||
|
description: String,
|
||||||
|
prerequisite: Set<Lowering> = emptySet()
|
||||||
|
) = BodyLowering(name, description, prerequisite.map { it.modulePhase }.toSet(), lowering)
|
||||||
|
|
||||||
|
fun SameTypeNamedPhaseWrapper<JsIrBackendContext, IrModuleFragment>.toModuleLowering() = ModuleLowering(this.name, this)
|
||||||
|
|
||||||
private val validateIrBeforeLowering = makeCustomJsModulePhase(
|
private val validateIrBeforeLowering = makeCustomJsModulePhase(
|
||||||
{ context, module -> validationCallback(context, module) },
|
{ context, module -> validationCallback(context, module) },
|
||||||
name = "ValidateIrBeforeLowering",
|
name = "ValidateIrBeforeLowering",
|
||||||
description = "Validate IR before lowering"
|
description = "Validate IR before lowering"
|
||||||
)
|
).toModuleLowering()
|
||||||
|
|
||||||
private val validateIrAfterLowering = makeCustomJsModulePhase(
|
private val validateIrAfterLowering = makeCustomJsModulePhase(
|
||||||
{ context, module -> validationCallback(context, module) },
|
{ context, module -> validationCallback(context, module) },
|
||||||
name = "ValidateIrAfterLowering",
|
name = "ValidateIrAfterLowering",
|
||||||
description = "Validate IR after lowering"
|
description = "Validate IR after lowering"
|
||||||
|
).toModuleLowering()
|
||||||
|
|
||||||
|
val scriptRemoveReceiverLowering = makeIrModulePhase(
|
||||||
|
::ScriptRemoveReceiverLowering,
|
||||||
|
name = "ScriptRemoveReceiver",
|
||||||
|
description = "Remove receivers for declarations in script"
|
||||||
|
).toModuleLowering()
|
||||||
|
|
||||||
|
val createScriptFunctionsPhase = makeJsModulePhase(
|
||||||
|
::CreateScriptFunctionsPhase,
|
||||||
|
name = "CreateScriptFunctionsPhase",
|
||||||
|
description = "Create functions for initialize and evaluate script"
|
||||||
|
).toModuleLowering()
|
||||||
|
|
||||||
|
private val moveBodilessDeclarationsToSeparatePlacePhase = makeDeclarationTransformerPhase(
|
||||||
|
::MoveBodilessDeclarationsToSeparatePlaceLowering,
|
||||||
|
name = "MoveBodilessDeclarationsToSeparatePlaceLowering",
|
||||||
|
description = "Move bodiless declarations to a separate place"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val expectDeclarationsRemovingPhase = makeJsModulePhase(
|
private val expectDeclarationsRemovingPhase = makeDeclarationTransformerPhase(
|
||||||
::ExpectDeclarationsRemoveLowering,
|
::ExpectDeclarationsRemoveLowering,
|
||||||
name = "ExpectDeclarationsRemoving",
|
name = "ExpectDeclarationsRemoving",
|
||||||
description = "Remove expect declaration from module fragment"
|
description = "Remove expect declaration from module fragment"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val lateinitNullableFieldsPhase = makeJsModulePhase(
|
private val lateinitNullableFieldsPhase = makeDeclarationTransformerPhase(
|
||||||
::NullableFieldsForLateinitCreationLowering,
|
::NullableFieldsForLateinitCreationLowering,
|
||||||
name = "LateinitNullableFields",
|
name = "LateinitNullableFields",
|
||||||
description = "Create nullable fields for lateinit properties"
|
description = "Create nullable fields for lateinit properties"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val lateinitDeclarationLoweringPhase = makeJsModulePhase(
|
private val lateinitDeclarationLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::NullableFieldsDeclarationLowering,
|
::NullableFieldsDeclarationLowering,
|
||||||
name = "LateinitDeclarations",
|
name = "LateinitDeclarations",
|
||||||
description = "Reference nullable fields from properties and getters + insert checks"
|
description = "Reference nullable fields from properties and getters + insert checks"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val lateinitUsageLoweringPhase = makeJsModulePhase(
|
private val lateinitUsageLoweringPhase = makeBodyLoweringPhase(
|
||||||
::LateinitUsageLowering,
|
::LateinitUsageLowering,
|
||||||
name = "LateinitUsage",
|
name = "LateinitUsage",
|
||||||
description = "Insert checks for lateinit field references"
|
description = "Insert checks for lateinit field references"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val stripTypeAliasDeclarationsPhase = makeJsModulePhase(
|
private val stripTypeAliasDeclarationsPhase = makeDeclarationTransformerPhase(
|
||||||
{ StripTypeAliasDeclarationsLowering() },
|
{ StripTypeAliasDeclarationsLowering() },
|
||||||
name = "StripTypeAliasDeclarations",
|
name = "StripTypeAliasDeclarations",
|
||||||
description = "Strip typealias declarations"
|
description = "Strip typealias declarations"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO make all lambda-related stuff work with IrFunctionExpression and drop this phase
|
// TODO make all lambda-related stuff work with IrFunctionExpression and drop this phase
|
||||||
private val provisionalFunctionExpressionPhase = makeJsModulePhase(
|
private val provisionalFunctionExpressionPhase = makeBodyLoweringPhase(
|
||||||
{ ProvisionalFunctionExpressionLowering() },
|
{ ProvisionalFunctionExpressionLowering() },
|
||||||
name = "FunctionExpression",
|
name = "FunctionExpression",
|
||||||
description = "Transform IrFunctionExpression to a local function reference"
|
description = "Transform IrFunctionExpression to a local function reference"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val arrayConstructorPhase = makeJsModulePhase(
|
private val arrayConstructorPhase = makeBodyLoweringPhase(
|
||||||
::ArrayConstructorLowering,
|
::ArrayConstructorLowering,
|
||||||
name = "ArrayConstructor",
|
name = "ArrayConstructor",
|
||||||
description = "Transform `Array(size) { index -> value }` into a loop"
|
description = "Transform `Array(size) { index -> value }` into a loop"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val functionInliningPhase = makeJsModulePhase(
|
private val functionInliningPhase = makeBodyLoweringPhase(
|
||||||
::FunctionInlining,
|
::FunctionInlining,
|
||||||
name = "FunctionInliningPhase",
|
name = "FunctionInliningPhase",
|
||||||
description = "Perform function inlining",
|
description = "Perform function inlining",
|
||||||
prerequisite = setOf(expectDeclarationsRemovingPhase)
|
prerequisite = setOf(expectDeclarationsRemovingPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val copyInlineFunctionBodyLoweringPhase = makeJsModulePhase(
|
private val copyInlineFunctionBodyLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::CopyInlineFunctionBodyLowering,
|
::CopyInlineFunctionBodyLowering,
|
||||||
name = "CopyInlineFunctionBody",
|
name = "CopyInlineFunctionBody",
|
||||||
description = "Copy inline function body",
|
description = "Copy inline function body",
|
||||||
prerequisite = setOf(functionInliningPhase)
|
prerequisite = setOf(functionInliningPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeJsModulePhase(
|
private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
{ RemoveInlineFunctionsWithReifiedTypeParametersLowering() },
|
{ RemoveInlineFunctionsWithReifiedTypeParametersLowering() },
|
||||||
name = "RemoveInlineFunctionsWithReifiedTypeParametersLowering",
|
name = "RemoveInlineFunctionsWithReifiedTypeParametersLowering",
|
||||||
description = "Remove Inline functions with reified parameters from context",
|
description = "Remove Inline functions with reified parameters from context",
|
||||||
prerequisite = setOf(functionInliningPhase)
|
prerequisite = setOf(functionInliningPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val throwableSuccessorsLoweringPhase = makeJsModulePhase(
|
private val throwableSuccessorsLoweringPhase = makeBodyLoweringPhase(
|
||||||
::ThrowableLowering,
|
::ThrowableLowering,
|
||||||
name = "ThrowableLowering",
|
name = "ThrowableLowering",
|
||||||
description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions"
|
description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val tailrecLoweringPhase = makeJsModulePhase(
|
private val tailrecLoweringPhase = makeBodyLoweringPhase(
|
||||||
::TailrecLowering,
|
::TailrecLowering,
|
||||||
name = "TailrecLowering",
|
name = "TailrecLowering",
|
||||||
description = "Replace `tailrec` callsites with equivalent loop"
|
description = "Replace `tailrec` callsites with equivalent loop"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumClassConstructorLoweringPhase = makeJsModulePhase(
|
private val enumClassConstructorLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::EnumClassConstructorLowering,
|
::EnumClassConstructorLowering,
|
||||||
name = "EnumClassConstructorLowering",
|
name = "EnumClassConstructorLowering",
|
||||||
description = "Transform Enum Class into regular Class"
|
description = "Transform Enum Class into regular Class"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumClassConstructorBodyLoweringPhase = makeJsModulePhase(
|
private val enumClassConstructorBodyLoweringPhase = makeBodyLoweringPhase(
|
||||||
::EnumClassConstructorBodyTransformer,
|
::EnumClassConstructorBodyTransformer,
|
||||||
name = "EnumClassConstructorBodyLowering",
|
name = "EnumClassConstructorBodyLowering",
|
||||||
description = "Transform Enum Class into regular Class"
|
description = "Transform Enum Class into regular Class"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
private val enumEntryInstancesLoweringPhase = makeJsModulePhase(
|
private val enumEntryInstancesLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::EnumEntryInstancesLowering,
|
::EnumEntryInstancesLowering,
|
||||||
name = "EnumEntryInstancesLowering",
|
name = "EnumEntryInstancesLowering",
|
||||||
description = "Create instance variable for each enum entry initialized with `null`",
|
description = "Create instance variable for each enum entry initialized with `null`",
|
||||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumEntryInstancesBodyLoweringPhase = makeJsModulePhase(
|
private val enumEntryInstancesBodyLoweringPhase = makeBodyLoweringPhase(
|
||||||
::EnumEntryInstancesBodyLowering,
|
::EnumEntryInstancesBodyLowering,
|
||||||
name = "EnumEntryInstancesBodyLowering",
|
name = "EnumEntryInstancesBodyLowering",
|
||||||
description = "Insert enum entry field initialization into correxposnding class constructors",
|
description = "Insert enum entry field initialization into correxposnding class constructors",
|
||||||
prerequisite = setOf(enumEntryInstancesLoweringPhase)
|
prerequisite = setOf(enumEntryInstancesLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumClassCreateInitializerLoweringPhase = makeJsModulePhase(
|
private val enumClassCreateInitializerLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::EnumClassCreateInitializerLowering,
|
::EnumClassCreateInitializerLowering,
|
||||||
name = "EnumClassCreateInitializerLowering",
|
name = "EnumClassCreateInitializerLowering",
|
||||||
description = "Create initializer for enum entries",
|
description = "Create initializer for enum entries",
|
||||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumEntryCreateGetInstancesFunsLoweringPhase = makeJsModulePhase(
|
private val enumEntryCreateGetInstancesFunsLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::EnumEntryCreateGetInstancesFunsLowering,
|
::EnumEntryCreateGetInstancesFunsLowering,
|
||||||
name = "EnumEntryCreateGetInstancesFunsLowering",
|
name = "EnumEntryCreateGetInstancesFunsLowering",
|
||||||
description = "Create enumEntry_getInstance functions",
|
description = "Create enumEntry_getInstance functions",
|
||||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumSyntheticFunsLoweringPhase = makeJsModulePhase(
|
private val enumSyntheticFunsLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::EnumSyntheticFunctionsLowering,
|
::EnumSyntheticFunctionsLowering,
|
||||||
name = "EnumSyntheticFunctionsLowering",
|
name = "EnumSyntheticFunctionsLowering",
|
||||||
description = "Implement `valueOf` and `values`",
|
description = "Implement `valueOf` and `values`",
|
||||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumUsageLoweringPhase = makeJsModulePhase(
|
private val enumUsageLoweringPhase = makeBodyLoweringPhase(
|
||||||
::EnumUsageLowering,
|
::EnumUsageLowering,
|
||||||
name = "EnumUsageLowering",
|
name = "EnumUsageLowering",
|
||||||
description = "Replace enum access with invocation of corresponding function",
|
description = "Replace enum access with invocation of corresponding function",
|
||||||
prerequisite = setOf(enumEntryCreateGetInstancesFunsLoweringPhase)
|
prerequisite = setOf(enumEntryCreateGetInstancesFunsLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val enumEntryRemovalLoweringPhase = makeJsModulePhase(
|
private val enumEntryRemovalLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::EnumClassRemoveEntriesLowering,
|
::EnumClassRemoveEntriesLowering,
|
||||||
name = "EnumEntryRemovalLowering",
|
name = "EnumEntryRemovalLowering",
|
||||||
description = "Replace enum entry with corresponding class",
|
description = "Replace enum entry with corresponding class",
|
||||||
prerequisite = setOf(enumUsageLoweringPhase)
|
prerequisite = setOf(enumUsageLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val sharedVariablesLoweringPhase = makeJsModulePhase(
|
private val sharedVariablesLoweringPhase = makeBodyLoweringPhase(
|
||||||
::SharedVariablesLowering,
|
::SharedVariablesLowering,
|
||||||
name = "SharedVariablesLowering",
|
name = "SharedVariablesLowering",
|
||||||
description = "Box captured mutable variables"
|
description = "Box captured mutable variables"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val returnableBlockLoweringPhase = makeJsModulePhase(
|
private val returnableBlockLoweringPhase = makeBodyLoweringPhase(
|
||||||
::ReturnableBlockLowering,
|
::ReturnableBlockLowering,
|
||||||
name = "ReturnableBlockLowering",
|
name = "ReturnableBlockLowering",
|
||||||
description = "Replace returnable block with do-while loop",
|
description = "Replace returnable block with do-while loop",
|
||||||
prerequisite = setOf(functionInliningPhase)
|
prerequisite = setOf(functionInliningPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val forLoopsLoweringPhase = makeJsModulePhase(
|
private val forLoopsLoweringPhase = makeBodyLoweringPhase(
|
||||||
::ForLoopsLowering,
|
::ForLoopsLowering,
|
||||||
name = "ForLoopsLowering",
|
name = "ForLoopsLowering",
|
||||||
description = "[Optimization] For loops lowering"
|
description = "[Optimization] For loops lowering"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val propertyAccessorInlinerLoweringPhase = makeJsModulePhase(
|
private val propertyAccessorInlinerLoweringPhase = makeBodyLoweringPhase(
|
||||||
::PropertyAccessorInlineLowering,
|
::PropertyAccessorInlineLowering,
|
||||||
name = "PropertyAccessorInlineLowering",
|
name = "PropertyAccessorInlineLowering",
|
||||||
description = "[Optimization] Inline property accessors"
|
description = "[Optimization] Inline property accessors"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val foldConstantLoweringPhase = makeJsModulePhase(
|
private val foldConstantLoweringPhase = makeBodyLoweringPhase(
|
||||||
{ FoldConstantLowering(it, true) },
|
{ FoldConstantLowering(it, true) },
|
||||||
name = "FoldConstantLowering",
|
name = "FoldConstantLowering",
|
||||||
description = "[Optimization] Constant Folding",
|
description = "[Optimization] Constant Folding",
|
||||||
prerequisite = setOf(propertyAccessorInlinerLoweringPhase)
|
prerequisite = setOf(propertyAccessorInlinerLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val localDelegatedPropertiesLoweringPhase = makeJsModulePhase(
|
private val localDelegatedPropertiesLoweringPhase = makeBodyLoweringPhase(
|
||||||
{ LocalDelegatedPropertiesLowering() },
|
{ LocalDelegatedPropertiesLowering() },
|
||||||
name = "LocalDelegatedPropertiesLowering",
|
name = "LocalDelegatedPropertiesLowering",
|
||||||
description = "Transform Local Delegated properties"
|
description = "Transform Local Delegated properties"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val localDeclarationsLoweringPhase = makeJsModulePhase(
|
private val localDeclarationsLoweringPhase = makeBodyLoweringPhase(
|
||||||
::LocalDeclarationsLowering,
|
::LocalDeclarationsLowering,
|
||||||
name = "LocalDeclarationsLowering",
|
name = "LocalDeclarationsLowering",
|
||||||
description = "Move local declarations into nearest declaration container",
|
description = "Move local declarations into nearest declaration container",
|
||||||
prerequisite = setOf(sharedVariablesLoweringPhase, localDelegatedPropertiesLoweringPhase)
|
prerequisite = setOf(sharedVariablesLoweringPhase, localDelegatedPropertiesLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val localClassExtractionPhase = makeJsModulePhase(
|
private val localClassExtractionPhase = makeBodyLoweringPhase(
|
||||||
::LocalClassPopupLowering,
|
::LocalClassPopupLowering,
|
||||||
name = "LocalClassExtractionPhase",
|
name = "LocalClassExtractionPhase",
|
||||||
description = "Move local declarations into nearest declaration container",
|
description = "Move local declarations into nearest declaration container",
|
||||||
prerequisite = setOf(localDeclarationsLoweringPhase)
|
prerequisite = setOf(localDeclarationsLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val innerClassesLoweringPhase = makeJsModulePhase(
|
private val innerClassesLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::InnerClassesLowering,
|
::InnerClassesLowering,
|
||||||
name = "InnerClassesLowering",
|
name = "InnerClassesLowering",
|
||||||
description = "Capture outer this reference to inner class"
|
description = "Capture outer this reference to inner class"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val innerClassesMemberBodyLoweringPhase = makeJsModulePhase(
|
private val innerClassesMemberBodyLoweringPhase = makeBodyLoweringPhase(
|
||||||
::InnerClassesMemberBodyLowering,
|
::InnerClassesMemberBodyLowering,
|
||||||
name = "InnerClassesMemberBody",
|
name = "InnerClassesMemberBody",
|
||||||
description = "Replace `this` with 'outer this' field references",
|
description = "Replace `this` with 'outer this' field references",
|
||||||
prerequisite = setOf(innerClassesLoweringPhase)
|
prerequisite = setOf(innerClassesLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val innerClassConstructorCallsLoweringPhase = makeJsModulePhase(
|
private val innerClassConstructorCallsLoweringPhase = makeBodyLoweringPhase(
|
||||||
::InnerClassConstructorCallsLowering,
|
::InnerClassConstructorCallsLowering,
|
||||||
name = "InnerClassConstructorCallsLowering",
|
name = "InnerClassConstructorCallsLowering",
|
||||||
description = "Replace inner class constructor invocation"
|
description = "Replace inner class constructor invocation"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val suspendFunctionsLoweringPhase = makeJsModulePhase(
|
private val suspendFunctionsLoweringPhase = makeBodyLoweringPhase(
|
||||||
::JsSuspendFunctionsLowering,
|
::JsSuspendFunctionsLowering,
|
||||||
name = "SuspendFunctionsLowering",
|
name = "SuspendFunctionsLowering",
|
||||||
description = "Transform suspend functions into CoroutineImpl instance and build state machine"
|
description = "Transform suspend functions into CoroutineImpl instance and build state machine"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val suspendLambdasRemovalLoweringPhase = makeJsModulePhase(
|
private val suspendLambdasRemovalLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
{ RemoveSuspendLambdas() },
|
{ RemoveSuspendLambdas() },
|
||||||
name = "RemoveSuspendLambdas",
|
name = "RemoveSuspendLambdas",
|
||||||
description = "Remove suspend lambdas"
|
description = "Remove suspend lambdas"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val privateMembersLoweringPhase = makeJsModulePhase(
|
private val privateMembersLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::PrivateMembersLowering,
|
::PrivateMembersLowering,
|
||||||
name = "PrivateMembersLowering",
|
name = "PrivateMembersLowering",
|
||||||
description = "Extract private members from classes"
|
description = "Extract private members from classes"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val privateMemberUsagesLoweringPhase = makeJsModulePhase(
|
private val privateMemberUsagesLoweringPhase = makeBodyLoweringPhase(
|
||||||
::PrivateMemberBodiesLowering,
|
::PrivateMemberBodiesLowering,
|
||||||
name = "PrivateMemberUsagesLowering",
|
name = "PrivateMemberUsagesLowering",
|
||||||
description = "Rewrite the private member usages"
|
description = "Rewrite the private member usages"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val callableReferenceLoweringPhase = makeJsModulePhase(
|
private val callableReferenceLoweringPhase = makeBodyLoweringPhase(
|
||||||
::CallableReferenceLowering,
|
::CallableReferenceLowering,
|
||||||
name = "CallableReferenceLowering",
|
name = "CallableReferenceLowering",
|
||||||
description = "Handle callable references",
|
description = "Handle callable references",
|
||||||
@@ -312,163 +382,163 @@ private val callableReferenceLoweringPhase = makeJsModulePhase(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val defaultArgumentStubGeneratorPhase = makeJsModulePhase(
|
private val defaultArgumentStubGeneratorPhase = makeDeclarationTransformerPhase(
|
||||||
::JsDefaultArgumentStubGenerator,
|
::JsDefaultArgumentStubGenerator,
|
||||||
name = "DefaultArgumentStubGenerator",
|
name = "DefaultArgumentStubGenerator",
|
||||||
description = "Generate synthetic stubs for functions with default parameter values"
|
description = "Generate synthetic stubs for functions with default parameter values"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val defaultArgumentPatchOverridesPhase = makeJsModulePhase(
|
private val defaultArgumentPatchOverridesPhase = makeDeclarationTransformerPhase(
|
||||||
::DefaultParameterPatchOverridenSymbolsLowering,
|
::DefaultParameterPatchOverridenSymbolsLowering,
|
||||||
name = "DefaultArgumentsPatchOverrides",
|
name = "DefaultArgumentsPatchOverrides",
|
||||||
description = "Patch overrides for fake override dispatch functions",
|
description = "Patch overrides for fake override dispatch functions",
|
||||||
prerequisite = setOf(defaultArgumentStubGeneratorPhase)
|
prerequisite = setOf(defaultArgumentStubGeneratorPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val defaultParameterInjectorPhase = makeJsModulePhase(
|
private val defaultParameterInjectorPhase = makeBodyLoweringPhase(
|
||||||
{ context -> DefaultParameterInjector(context, skipExternalMethods = true, forceSetOverrideSymbols = false) },
|
{ context -> DefaultParameterInjector(context, skipExternalMethods = true, forceSetOverrideSymbols = false) },
|
||||||
name = "DefaultParameterInjector",
|
name = "DefaultParameterInjector",
|
||||||
description = "Replace callsite with default parameters with corresponding stub function",
|
description = "Replace callsite with default parameters with corresponding stub function",
|
||||||
prerequisite = setOf(callableReferenceLoweringPhase, innerClassesLoweringPhase)
|
prerequisite = setOf(callableReferenceLoweringPhase, innerClassesLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val defaultParameterCleanerPhase = makeJsModulePhase(
|
private val defaultParameterCleanerPhase = makeDeclarationTransformerPhase(
|
||||||
::DefaultParameterCleaner,
|
::DefaultParameterCleaner,
|
||||||
name = "DefaultParameterCleaner",
|
name = "DefaultParameterCleaner",
|
||||||
description = "Clean default parameters up"
|
description = "Clean default parameters up"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val jsDefaultCallbackGeneratorPhase = makeJsModulePhase(
|
private val jsDefaultCallbackGeneratorPhase = makeBodyLoweringPhase(
|
||||||
::JsDefaultCallbackGenerator,
|
::JsDefaultCallbackGenerator,
|
||||||
name = "JsDefaultCallbackGenerator",
|
name = "JsDefaultCallbackGenerator",
|
||||||
description = "Build binding for super calls with default parameters"
|
description = "Build binding for super calls with default parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val varargLoweringPhase = makeJsModulePhase(
|
private val varargLoweringPhase = makeBodyLoweringPhase(
|
||||||
::VarargLowering,
|
::VarargLowering,
|
||||||
name = "VarargLowering",
|
name = "VarargLowering",
|
||||||
description = "Lower vararg arguments",
|
description = "Lower vararg arguments",
|
||||||
prerequisite = setOf(callableReferenceLoweringPhase)
|
prerequisite = setOf(callableReferenceLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val propertiesLoweringPhase = makeJsModulePhase(
|
private val propertiesLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
{ PropertiesLowering() },
|
{ PropertiesLowering() },
|
||||||
name = "PropertiesLowering",
|
name = "PropertiesLowering",
|
||||||
description = "Move fields and accessors out from its property"
|
description = "Move fields and accessors out from its property"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val primaryConstructorLoweringPhase = makeJsModulePhase(
|
private val primaryConstructorLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::PrimaryConstructorLowering,
|
::PrimaryConstructorLowering,
|
||||||
name = "PrimaryConstructorLowering",
|
name = "PrimaryConstructorLowering",
|
||||||
description = "Creates primary constructor if it doesn't exist",
|
description = "Creates primary constructor if it doesn't exist",
|
||||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val delegateToPrimaryConstructorLoweringPhase = makeJsModulePhase(
|
private val delegateToPrimaryConstructorLoweringPhase = makeBodyLoweringPhase(
|
||||||
::DelegateToSyntheticPrimaryConstructor,
|
::DelegateToSyntheticPrimaryConstructor,
|
||||||
name = "DelegateToSyntheticPrimaryConstructor",
|
name = "DelegateToSyntheticPrimaryConstructor",
|
||||||
description = "Delegates to synthetic primary constructor",
|
description = "Delegates to synthetic primary constructor",
|
||||||
prerequisite = setOf(primaryConstructorLoweringPhase)
|
prerequisite = setOf(primaryConstructorLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val annotationConstructorLowering = makeJsModulePhase(
|
private val annotationConstructorLowering = makeDeclarationTransformerPhase(
|
||||||
::AnnotationConstructorLowering,
|
::AnnotationConstructorLowering,
|
||||||
name = "AnnotationConstructorLowering",
|
name = "AnnotationConstructorLowering",
|
||||||
description = "Generate annotation constructor body"
|
description = "Generate annotation constructor body"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val initializersLoweringPhase = makeJsModulePhase(
|
private val initializersLoweringPhase = makeBodyLoweringPhase(
|
||||||
::InitializersLowering,
|
::InitializersLowering,
|
||||||
name = "InitializersLowering",
|
name = "InitializersLowering",
|
||||||
description = "Merge init block and field initializers into [primary] constructor",
|
description = "Merge init block and field initializers into [primary] constructor",
|
||||||
prerequisite = setOf(enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase, annotationConstructorLowering)
|
prerequisite = setOf(enumClassConstructorLoweringPhase, primaryConstructorLoweringPhase, annotationConstructorLowering)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val initializersCleanupLoweringPhase = makeJsModulePhase(
|
private val initializersCleanupLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::InitializersCleanupLowering,
|
::InitializersCleanupLowering,
|
||||||
name = "InitializersCleanupLowering",
|
name = "InitializersCleanupLowering",
|
||||||
description = "Remove non-static anonymous initializers and field init expressions",
|
description = "Remove non-static anonymous initializers and field init expressions",
|
||||||
prerequisite = setOf(initializersLoweringPhase)
|
prerequisite = setOf(initializersLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val multipleCatchesLoweringPhase = makeJsModulePhase(
|
private val multipleCatchesLoweringPhase = makeBodyLoweringPhase(
|
||||||
::MultipleCatchesLowering,
|
::MultipleCatchesLowering,
|
||||||
name = "MultipleCatchesLowering",
|
name = "MultipleCatchesLowering",
|
||||||
description = "Replace multiple catches with single one"
|
description = "Replace multiple catches with single one"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val bridgesConstructionPhase = makeJsModulePhase(
|
private val bridgesConstructionPhase = makeDeclarationTransformerPhase(
|
||||||
::BridgesConstruction,
|
::BridgesConstruction,
|
||||||
name = "BridgesConstruction",
|
name = "BridgesConstruction",
|
||||||
description = "Generate bridges",
|
description = "Generate bridges",
|
||||||
prerequisite = setOf(suspendFunctionsLoweringPhase)
|
prerequisite = setOf(suspendFunctionsLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val typeOperatorLoweringPhase = makeJsModulePhase(
|
private val typeOperatorLoweringPhase = makeBodyLoweringPhase(
|
||||||
::TypeOperatorLowering,
|
::TypeOperatorLowering,
|
||||||
name = "TypeOperatorLowering",
|
name = "TypeOperatorLowering",
|
||||||
description = "Lower IrTypeOperator with corresponding logic",
|
description = "Lower IrTypeOperator with corresponding logic",
|
||||||
prerequisite = setOf(bridgesConstructionPhase, removeInlineFunctionsWithReifiedTypeParametersLoweringPhase)
|
prerequisite = setOf(bridgesConstructionPhase, removeInlineFunctionsWithReifiedTypeParametersLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val secondaryConstructorLoweringPhase = makeJsModulePhase(
|
private val secondaryConstructorLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::SecondaryConstructorLowering,
|
::SecondaryConstructorLowering,
|
||||||
name = "SecondaryConstructorLoweringPhase",
|
name = "SecondaryConstructorLoweringPhase",
|
||||||
description = "Generate static functions for each secondary constructor",
|
description = "Generate static functions for each secondary constructor",
|
||||||
prerequisite = setOf(innerClassesLoweringPhase)
|
prerequisite = setOf(innerClassesLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val secondaryFactoryInjectorLoweringPhase = makeJsModulePhase(
|
private val secondaryFactoryInjectorLoweringPhase = makeBodyLoweringPhase(
|
||||||
::SecondaryFactoryInjectorLowering,
|
::SecondaryFactoryInjectorLowering,
|
||||||
name = "SecondaryFactoryInjectorLoweringPhase",
|
name = "SecondaryFactoryInjectorLoweringPhase",
|
||||||
description = "Replace usage of secondary constructor with corresponding static function",
|
description = "Replace usage of secondary constructor with corresponding static function",
|
||||||
prerequisite = setOf(innerClassesLoweringPhase)
|
prerequisite = setOf(innerClassesLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val inlineClassDeclarationLoweringPhase = makeJsModulePhase(
|
private val inlineClassDeclarationLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
{ InlineClassLowering(it).inlineClassDeclarationLowering },
|
{ InlineClassLowering(it).inlineClassDeclarationLowering },
|
||||||
name = "InlineClassDeclarationLowering",
|
name = "InlineClassDeclarationLowering",
|
||||||
description = "Handle inline class declarations"
|
description = "Handle inline class declarations"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val inlineClassUsageLoweringPhase = makeJsModulePhase(
|
private val inlineClassUsageLoweringPhase = makeBodyLoweringPhase(
|
||||||
{ InlineClassLowering(it).inlineClassUsageLowering },
|
{ InlineClassLowering(it).inlineClassUsageLowering },
|
||||||
name = "InlineClassUsageLowering",
|
name = "InlineClassUsageLowering",
|
||||||
description = "Handle inline class usages"
|
description = "Handle inline class usages"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val autoboxingTransformerPhase = makeJsModulePhase(
|
private val autoboxingTransformerPhase = makeBodyLoweringPhase(
|
||||||
::AutoboxingTransformer,
|
::AutoboxingTransformer,
|
||||||
name = "AutoboxingTransformer",
|
name = "AutoboxingTransformer",
|
||||||
description = "Insert box/unbox intrinsics"
|
description = "Insert box/unbox intrinsics"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val blockDecomposerLoweringPhase = makeJsModulePhase(
|
private val blockDecomposerLoweringPhase = makeBodyLoweringPhase(
|
||||||
::JsBlockDecomposerLowering,
|
::JsBlockDecomposerLowering,
|
||||||
name = "BlockDecomposerLowering",
|
name = "BlockDecomposerLowering",
|
||||||
description = "Transform statement-like-expression nodes into pure-statement to make it easily transform into JS",
|
description = "Transform statement-like-expression nodes into pure-statement to make it easily transform into JS",
|
||||||
prerequisite = setOf(typeOperatorLoweringPhase, suspendFunctionsLoweringPhase)
|
prerequisite = setOf(typeOperatorLoweringPhase, suspendFunctionsLoweringPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val classReferenceLoweringPhase = makeJsModulePhase(
|
private val classReferenceLoweringPhase = makeBodyLoweringPhase(
|
||||||
::ClassReferenceLowering,
|
::ClassReferenceLowering,
|
||||||
name = "ClassReferenceLowering",
|
name = "ClassReferenceLowering",
|
||||||
description = "Handle class references"
|
description = "Handle class references"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val primitiveCompanionLoweringPhase = makeJsModulePhase(
|
private val primitiveCompanionLoweringPhase = makeBodyLoweringPhase(
|
||||||
::PrimitiveCompanionLowering,
|
::PrimitiveCompanionLowering,
|
||||||
name = "PrimitiveCompanionLowering",
|
name = "PrimitiveCompanionLowering",
|
||||||
description = "Replace common companion object access with platform one"
|
description = "Replace common companion object access with platform one"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val constLoweringPhase = makeJsModulePhase(
|
private val constLoweringPhase = makeBodyLoweringPhase(
|
||||||
::ConstLowering,
|
::ConstLowering,
|
||||||
name = "ConstLowering",
|
name = "ConstLowering",
|
||||||
description = "Wrap Long and Char constants into constructor invocation"
|
description = "Wrap Long and Char constants into constructor invocation"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val callsLoweringPhase = makeJsModulePhase(
|
private val callsLoweringPhase = makeBodyLoweringPhase(
|
||||||
::CallsLowering,
|
::CallsLowering,
|
||||||
name = "CallsLowering",
|
name = "CallsLowering",
|
||||||
description = "Handle intrinsics"
|
description = "Handle intrinsics"
|
||||||
@@ -478,27 +548,27 @@ private val testGenerationPhase = makeJsModulePhase(
|
|||||||
::TestGenerator,
|
::TestGenerator,
|
||||||
name = "TestGenerationLowering",
|
name = "TestGenerationLowering",
|
||||||
description = "Generate invocations to kotlin.test suite and test functions"
|
description = "Generate invocations to kotlin.test suite and test functions"
|
||||||
)
|
).toModuleLowering()
|
||||||
|
|
||||||
private val staticMembersLoweringPhase = makeJsModulePhase(
|
private val staticMembersLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::StaticMembersLowering,
|
::StaticMembersLowering,
|
||||||
name = "StaticMembersLowering",
|
name = "StaticMembersLowering",
|
||||||
description = "Move static member declarations to top-level"
|
description = "Move static member declarations to top-level"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val objectDeclarationLoweringPhase = makeJsModulePhase(
|
private val objectDeclarationLoweringPhase = makeDeclarationTransformerPhase(
|
||||||
::ObjectDeclarationLowering,
|
::ObjectDeclarationLowering,
|
||||||
name = "ObjectDeclarationLowering",
|
name = "ObjectDeclarationLowering",
|
||||||
description = "Create lazy object instance generator functions"
|
description = "Create lazy object instance generator functions"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val objectUsageLoweringPhase = makeJsModulePhase(
|
private val objectUsageLoweringPhase = makeBodyLoweringPhase(
|
||||||
::ObjectUsageLowering,
|
::ObjectUsageLowering,
|
||||||
name = "ObjectUsageLowering",
|
name = "ObjectUsageLowering",
|
||||||
description = "Transform IrGetObjectValue into instance generator call"
|
description = "Transform IrGetObjectValue into instance generator call"
|
||||||
)
|
)
|
||||||
|
|
||||||
val phaseList: List<CompilerPhase<JsIrBackendContext, IrModuleFragment, IrModuleFragment>> = listOf(
|
val loweringList = listOf<Lowering>(
|
||||||
scriptRemoveReceiverLowering,
|
scriptRemoveReceiverLowering,
|
||||||
validateIrBeforeLowering,
|
validateIrBeforeLowering,
|
||||||
testGenerationPhase,
|
testGenerationPhase,
|
||||||
@@ -571,9 +641,12 @@ val phaseList: List<CompilerPhase<JsIrBackendContext, IrModuleFragment, IrModule
|
|||||||
validateIrAfterLowering
|
validateIrAfterLowering
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val pirLowerings = loweringList.filter { it is DeclarationLowering || it is BodyLowering } + staticMembersLoweringPhase
|
||||||
|
|
||||||
val jsPhases = namedIrModulePhase(
|
val jsPhases = namedIrModulePhase(
|
||||||
name = "IrModuleLowering",
|
name = "IrModuleLowering",
|
||||||
description = "IR module lowering",
|
description = "IR module lowering",
|
||||||
lower = phaseList.drop(1).fold(phaseList[0]) { acc: CompilerPhase<JsIrBackendContext, IrModuleFragment, IrModuleFragment>, phase ->
|
lower = loweringList.drop(1).fold(loweringList[0].modulePhase) { acc: CompilerPhase<JsIrBackendContext, IrModuleFragment, IrModuleFragment>, lowering ->
|
||||||
acc.then(phase)
|
acc.then(lowering.modulePhase)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js
|
package org.jetbrains.kotlin.ir.backend.js
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.DefaultMapping
|
import org.jetbrains.kotlin.backend.common.DefaultMapping
|
||||||
|
import org.jetbrains.kotlin.backend.common.Mapping
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
|
||||||
class JsMapping : DefaultMapping() {
|
class JsMapping : DefaultMapping() {
|
||||||
@@ -27,4 +28,23 @@ class JsMapping : DefaultMapping() {
|
|||||||
val enumConstructorOldToNewValueParameters = newMapping<IrValueDeclaration, IrValueParameter>()
|
val enumConstructorOldToNewValueParameters = newMapping<IrValueDeclaration, IrValueParameter>()
|
||||||
val enumEntryToCorrespondingField = newMapping<IrEnumEntry, IrField>()
|
val enumEntryToCorrespondingField = newMapping<IrEnumEntry, IrField>()
|
||||||
val enumClassToInitEntryInstancesFun = newMapping<IrClass, IrSimpleFunction>()
|
val enumClassToInitEntryInstancesFun = newMapping<IrClass, IrSimpleFunction>()
|
||||||
|
|
||||||
|
// Triggers `StageController.lazyLower` on access
|
||||||
|
override fun <K : IrDeclaration, V> newMapping(): Mapping.Delegate<K, V> = object : Mapping.Delegate<K, V>() {
|
||||||
|
private val map: MutableMap<K, V> = mutableMapOf()
|
||||||
|
|
||||||
|
override operator fun get(key: K): V? {
|
||||||
|
stageController.lazyLower(key)
|
||||||
|
return map[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
override operator fun set(key: K, value: V?) {
|
||||||
|
stageController.lazyLower(key)
|
||||||
|
if (value == null) {
|
||||||
|
map.remove(key)
|
||||||
|
} else {
|
||||||
|
map[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+145
-50
@@ -8,11 +8,124 @@ package org.jetbrains.kotlin.ir.backend.js
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrPersistingElementBase
|
import org.jetbrains.kotlin.ir.declarations.impl.IrBodyBase
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrDeclarationBase
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
|
import org.jetbrains.kotlin.ir.util.isLocal
|
||||||
|
|
||||||
open class MutableController(override var currentStage: Int = 0) : StageController {
|
open class MutableController(val context: JsIrBackendContext, val lowerings: List<Lowering>) : StageController {
|
||||||
|
|
||||||
override var bodiesEnabled: Boolean = true
|
override var currentStage: Int = 0
|
||||||
|
|
||||||
|
override fun lazyLower(declaration: IrDeclaration) {
|
||||||
|
if (declaration is IrDeclarationBase<*>) {
|
||||||
|
while (declaration.loweredUpTo + 1 < currentStage) {
|
||||||
|
val i = declaration.loweredUpTo + 1
|
||||||
|
withStage(i) {
|
||||||
|
// TODO a better way to skip declarations in external package fragments
|
||||||
|
if (declaration.removedOn > i && declaration !in context.externalDeclarations) {
|
||||||
|
|
||||||
|
when (val lowering = lowerings[i - 1]) {
|
||||||
|
is DeclarationLowering -> lowering.doApplyLoweringTo(declaration)
|
||||||
|
is BodyLowering -> {
|
||||||
|
// Handle local declarations in case they leak through types
|
||||||
|
if (declaration.isLocal) {
|
||||||
|
declaration.enclosingBody()?.let {
|
||||||
|
withStage(i + 1) { lazyLower(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declaration.loweredUpTo = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun lazyLower(body: IrBody) {
|
||||||
|
if (body is IrBodyBase<*>) {
|
||||||
|
for (i in (body.loweredUpTo + 1) until currentStage) {
|
||||||
|
withStage(i) {
|
||||||
|
if (body.container !in context.externalDeclarations) {
|
||||||
|
val lowering = lowerings[i - 1]
|
||||||
|
|
||||||
|
if (lowering is BodyLowering) {
|
||||||
|
bodyLowering {
|
||||||
|
lowering.bodyLowering(context).lower(body, body.container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body.loweredUpTo = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launches a lowering and applies it's results
|
||||||
|
private fun DeclarationLowering.doApplyLoweringTo(declaration: IrDeclarationBase<*>) {
|
||||||
|
val parentBefore = declaration.parent
|
||||||
|
val result = restrictTo(declaration) { this.declarationTransformer(context).transformFlat(declaration) }
|
||||||
|
if (result != null) {
|
||||||
|
result.forEach {
|
||||||
|
// Some of our lowerings rely on transformDeclarationsFlat
|
||||||
|
it.parent = parentBefore
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentBefore is IrDeclarationContainer) {
|
||||||
|
unrestrictDeclarationListsAccess {
|
||||||
|
|
||||||
|
// Field order matters for top level property initialization
|
||||||
|
val correspondingProperty = when (declaration) {
|
||||||
|
is IrSimpleFunction -> declaration.correspondingPropertySymbol?.owner
|
||||||
|
is IrField -> declaration.correspondingPropertySymbol?.owner
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = -1
|
||||||
|
parentBefore.declarations.forEachIndexed { i, v ->
|
||||||
|
if (v == declaration || index == -1 && v == correspondingProperty) {
|
||||||
|
index = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index != -1 && declaration !is IrProperty) {
|
||||||
|
if (parentBefore.declarations[index] == declaration) {
|
||||||
|
parentBefore.declarations.removeAt(index)
|
||||||
|
}
|
||||||
|
parentBefore.declarations.addAll(index, result)
|
||||||
|
} else {
|
||||||
|
parentBefore.declarations.addAll(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (declaration.parent == parentBefore && declaration !in result) {
|
||||||
|
declaration.removedOn = currentStage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds outermost body, containing the declarations
|
||||||
|
// Doesn't work in case of local declarations inside default arguments
|
||||||
|
// That might be fine as those shouldn't leak
|
||||||
|
private fun IrDeclaration.enclosingBody(): IrBody? {
|
||||||
|
var lastBodyContainer: IrDeclaration? = null
|
||||||
|
var parent = this.parent
|
||||||
|
while (parent is IrDeclaration) {
|
||||||
|
if (parent !is IrClass) {
|
||||||
|
lastBodyContainer = parent
|
||||||
|
}
|
||||||
|
parent = parent.parent
|
||||||
|
}
|
||||||
|
return lastBodyContainer?.run {
|
||||||
|
when (this) {
|
||||||
|
is IrFunction -> body // TODO What about local declarations inside default arguments?
|
||||||
|
is IrField -> initializer
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T> withStage(stage: Int, fn: () -> T): T {
|
override fun <T> withStage(stage: Int, fn: () -> T): T {
|
||||||
val prevStage = currentStage
|
val prevStage = currentStage
|
||||||
@@ -24,27 +137,45 @@ open class MutableController(override var currentStage: Int = 0) : StageControll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> withInitialIr(block: () -> T): T = restrictionImpl(null) { withStage(0, block) }
|
override fun <T> withInitialIr(block: () -> T): T = { withStage(0, block) }.withRestrictions(newRestrictedToDeclaration = null)
|
||||||
|
|
||||||
override fun <T> withInitialStateOf(declaration: IrDeclaration, block: () -> T): T = withStage((declaration as? IrPersistingElementBase<*>)?.createdOn ?: 0, block)
|
override fun <T> restrictTo(declaration: IrDeclaration, fn: () -> T): T = fn.withRestrictions(newRestrictedToDeclaration = declaration)
|
||||||
|
|
||||||
private var restricted: Boolean = false
|
override fun <T> bodyLowering(fn: () -> T): T = fn.withRestrictions(newBodiesEnabled = true, newRestricted = true, newDeclarationListsRestricted = true)
|
||||||
|
|
||||||
|
override fun <T> unrestrictDeclarationListsAccess(fn: () -> T): T = fn.withRestrictions(newDeclarationListsRestricted = false)
|
||||||
|
|
||||||
|
override fun canModify(element: IrElement): Boolean {
|
||||||
|
return true
|
||||||
|
// return !restricted || restrictedToDeclaration === element || element is IrPersistingElementBase<*> && element.createdOn == currentStage
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canAccessDeclarationsOf(irClass: IrClass): Boolean {
|
||||||
|
return !declarationListsRestricted || irClass.visibility == Visibilities.LOCAL && irClass !in context.extractedLocalClasses
|
||||||
|
}
|
||||||
|
|
||||||
private var restrictedToDeclaration: IrDeclaration? = null
|
private var restrictedToDeclaration: IrDeclaration? = null
|
||||||
|
// TODO flags?
|
||||||
|
override var bodiesEnabled: Boolean = true
|
||||||
|
private var restricted: Boolean = false
|
||||||
|
private var declarationListsRestricted = false
|
||||||
|
|
||||||
override fun <T> restrictTo(declaration: IrDeclaration, fn: () -> T): T = restrictionImpl(declaration, fn)
|
private inline fun <T> (() -> T).withRestrictions(
|
||||||
|
newRestrictedToDeclaration: IrDeclaration? = null,
|
||||||
private fun <T> restrictionImpl(declaration: IrDeclaration?, fn: () -> T): T {
|
newBodiesEnabled: Boolean? = null,
|
||||||
|
newRestricted: Boolean? = null,
|
||||||
|
newDeclarationListsRestricted: Boolean? = null
|
||||||
|
): T {
|
||||||
val prev = restrictedToDeclaration
|
val prev = restrictedToDeclaration
|
||||||
restrictedToDeclaration = declaration
|
restrictedToDeclaration = newRestrictedToDeclaration
|
||||||
val wereBodiesEnabled = bodiesEnabled
|
val wereBodiesEnabled = bodiesEnabled
|
||||||
bodiesEnabled = false
|
bodiesEnabled = newBodiesEnabled ?: bodiesEnabled
|
||||||
val wasRestricted = restricted
|
val wasRestricted = restricted
|
||||||
restricted = true
|
restricted = newRestricted ?: restricted
|
||||||
val wereDeclarationListsRestricted = declarationListsRestricted
|
val wereDeclarationListsRestricted = declarationListsRestricted
|
||||||
declarationListsRestricted = true
|
declarationListsRestricted = newDeclarationListsRestricted ?: declarationListsRestricted
|
||||||
try {
|
try {
|
||||||
return fn()
|
return this.invoke()
|
||||||
} finally {
|
} finally {
|
||||||
restrictedToDeclaration = prev
|
restrictedToDeclaration = prev
|
||||||
bodiesEnabled = wereBodiesEnabled
|
bodiesEnabled = wereBodiesEnabled
|
||||||
@@ -52,40 +183,4 @@ open class MutableController(override var currentStage: Int = 0) : StageControll
|
|||||||
declarationListsRestricted = wereDeclarationListsRestricted
|
declarationListsRestricted = wereDeclarationListsRestricted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> bodyLowering(fn: () -> T): T {
|
|
||||||
val wereBodiesEnabled = bodiesEnabled
|
|
||||||
bodiesEnabled = true
|
|
||||||
val wasRestricted = restricted
|
|
||||||
restricted = true
|
|
||||||
val wereDeclarationListsRestricted = declarationListsRestricted
|
|
||||||
declarationListsRestricted = true
|
|
||||||
try {
|
|
||||||
return fn()
|
|
||||||
} finally {
|
|
||||||
bodiesEnabled = wereBodiesEnabled
|
|
||||||
restricted = wasRestricted
|
|
||||||
declarationListsRestricted = wereDeclarationListsRestricted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canModify(element: IrElement): Boolean {
|
|
||||||
return !restricted || restrictedToDeclaration === element || element is IrPersistingElementBase<*> && element.createdOn == currentStage
|
|
||||||
}
|
|
||||||
|
|
||||||
private var declarationListsRestricted = false
|
|
||||||
|
|
||||||
override fun <T> unrestrictDeclarationListsAccess(fn: () -> T): T {
|
|
||||||
val wereDeclarationListsRestricted = declarationListsRestricted
|
|
||||||
declarationListsRestricted = false
|
|
||||||
try {
|
|
||||||
return fn()
|
|
||||||
} finally {
|
|
||||||
declarationListsRestricted = wereDeclarationListsRestricted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canAccessDeclarationsOf(irClass: IrClass): Boolean {
|
|
||||||
return !declarationListsRestricted || irClass.visibility == Visibilities.LOCAL /*|| currentStage == (irClass as? IrPersistingElementBase<*>)?.createdOn ?: 0*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
|||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaserState
|
import org.jetbrains.kotlin.backend.common.phaser.PhaserState
|
||||||
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.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
import org.jetbrains.kotlin.ir.backend.js.lower.generateTests
|
||||||
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.transformers.irToJs.IrModuleToJsTransformer
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsMainFunctionDetector
|
import org.jetbrains.kotlin.ir.backend.js.utils.JsMainFunctionDetector
|
||||||
@@ -27,16 +27,6 @@ import org.jetbrains.kotlin.library.KotlinLibrary
|
|||||||
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
|
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
|
||||||
|
|
||||||
fun sortDependencies(dependencies: Collection<IrModuleFragment>): Collection<IrModuleFragment> {
|
|
||||||
val mapping = dependencies.map { it.descriptor to it }.toMap()
|
|
||||||
|
|
||||||
return DFS.topologicalOrder(dependencies) { m ->
|
|
||||||
val descriptor = m.descriptor
|
|
||||||
descriptor.allDependencyModules.filter { it != descriptor }.map { mapping[it] }
|
|
||||||
}.reversed()
|
|
||||||
}
|
|
||||||
|
|
||||||
class CompilerResult(
|
class CompilerResult(
|
||||||
val jsCode: String?,
|
val jsCode: String?,
|
||||||
@@ -55,7 +45,8 @@ fun compile(
|
|||||||
mainArguments: List<String>?,
|
mainArguments: List<String>?,
|
||||||
exportedDeclarations: Set<FqName> = emptySet(),
|
exportedDeclarations: Set<FqName> = emptySet(),
|
||||||
generateFullJs: Boolean = true,
|
generateFullJs: Boolean = true,
|
||||||
generateDceJs: Boolean = false
|
generateDceJs: Boolean = false,
|
||||||
|
dceDriven: Boolean = false
|
||||||
): CompilerResult {
|
): CompilerResult {
|
||||||
stageController = object : StageController {}
|
stageController = object : StageController {}
|
||||||
|
|
||||||
@@ -93,17 +84,30 @@ fun compile(
|
|||||||
|
|
||||||
moveBodilessDeclarationsToSeparatePlace(context, moduleFragment)
|
moveBodilessDeclarationsToSeparatePlace(context, moduleFragment)
|
||||||
|
|
||||||
val controller = MutableController()
|
if (dceDriven) {
|
||||||
stageController = controller
|
|
||||||
|
|
||||||
val phaserState = PhaserState<IrModuleFragment>()
|
// TODO we should only generate tests for the current module
|
||||||
phaseList.forEachIndexed { index, phase ->
|
// TODO should be done incrementally
|
||||||
controller.currentStage = index + 1
|
generateTests(context, moduleFragment)
|
||||||
phase.invoke(phaseConfig, phaserState, context, moduleFragment)
|
|
||||||
|
val controller = MutableController(context, pirLowerings)
|
||||||
|
stageController = controller
|
||||||
|
|
||||||
|
controller.currentStage = controller.lowerings.size + 1
|
||||||
|
|
||||||
|
eliminateDeadDeclarations(moduleFragment, context, mainFunction)
|
||||||
|
|
||||||
|
stageController = object : StageController {
|
||||||
|
override val currentStage: Int = controller.currentStage
|
||||||
|
}
|
||||||
|
|
||||||
|
val transformer = IrModuleToJsTransformer(context, mainFunction, mainArguments)
|
||||||
|
return transformer.generateModule(moduleFragment, fullJs = true, dceJs = false)
|
||||||
|
} else {
|
||||||
|
jsPhases.invokeToplevel(phaseConfig, context, moduleFragment)
|
||||||
|
val transformer = IrModuleToJsTransformer(context, mainFunction, mainArguments)
|
||||||
|
return transformer.generateModule(moduleFragment, generateFullJs, generateDceJs)
|
||||||
}
|
}
|
||||||
|
|
||||||
val transformer = IrModuleToJsTransformer(context, mainFunction, mainArguments)
|
|
||||||
return transformer.generateModule(moduleFragment, generateFullJs, generateDceJs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateJsCode(
|
fun generateJsCode(
|
||||||
|
|||||||
-6
@@ -27,12 +27,6 @@ import org.jetbrains.kotlin.ir.types.IrType
|
|||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
val createScriptFunctionsPhase = makeIrModulePhase(
|
|
||||||
::CreateScriptFunctionsPhase,
|
|
||||||
name = "CreateScriptFunctionsPhase",
|
|
||||||
description = "Create functions for initialize and evaluate script"
|
|
||||||
)
|
|
||||||
|
|
||||||
private object SCRIPT_FUNCTION : IrDeclarationOriginImpl("SCRIPT_FUNCTION")
|
private object SCRIPT_FUNCTION : IrDeclarationOriginImpl("SCRIPT_FUNCTION")
|
||||||
|
|
||||||
class CreateScriptFunctionsPhase(val context: CommonBackendContext) : FileLoweringPass {
|
class CreateScriptFunctionsPhase(val context: CommonBackendContext) : FileLoweringPass {
|
||||||
|
|||||||
+22
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||||
import org.jetbrains.kotlin.backend.common.ir.addChild
|
import org.jetbrains.kotlin.backend.common.ir.addChild
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
||||||
@@ -17,6 +18,8 @@ import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
|
|||||||
import org.jetbrains.kotlin.ir.util.UniqId
|
import org.jetbrains.kotlin.ir.util.UniqId
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
private val BODILESS_BUILTIN_CLASSES = listOf(
|
private val BODILESS_BUILTIN_CLASSES = listOf(
|
||||||
@@ -89,12 +92,16 @@ class MoveBodilessDeclarationsToSeparatePlaceLowering(private val context: JsIrB
|
|||||||
|
|
||||||
context.packageLevelJsModules += externalPackageFragment
|
context.packageLevelJsModules += externalPackageFragment
|
||||||
|
|
||||||
|
declaration.collectAllExternalDeclarations()
|
||||||
|
|
||||||
return emptyList()
|
return emptyList()
|
||||||
} else {
|
} else {
|
||||||
val d = declaration as? IrDeclarationWithName ?: return null
|
val d = declaration as? IrDeclarationWithName ?: return null
|
||||||
|
|
||||||
if (isBuiltInClass(d)) {
|
if (isBuiltInClass(d)) {
|
||||||
context.bodilessBuiltInsPackageFragment.addChild(d)
|
context.bodilessBuiltInsPackageFragment.addChild(d)
|
||||||
|
d.collectAllExternalDeclarations()
|
||||||
|
|
||||||
return emptyList()
|
return emptyList()
|
||||||
} else if (d.isEffectivelyExternal()) {
|
} else if (d.isEffectivelyExternal()) {
|
||||||
if (d.getJsModule() != null)
|
if (d.getJsModule() != null)
|
||||||
@@ -103,10 +110,25 @@ class MoveBodilessDeclarationsToSeparatePlaceLowering(private val context: JsIrB
|
|||||||
externalPackageFragment.declarations += d
|
externalPackageFragment.declarations += d
|
||||||
d.parent = externalPackageFragment
|
d.parent = externalPackageFragment
|
||||||
|
|
||||||
|
d.collectAllExternalDeclarations()
|
||||||
|
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrDeclaration.collectAllExternalDeclarations() {
|
||||||
|
this.accept(object : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDeclaration(declaration: IrDeclaration) {
|
||||||
|
context.externalDeclarations.add(declaration)
|
||||||
|
super.visitDeclaration(declaration)
|
||||||
|
}
|
||||||
|
}, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+3
-1
@@ -57,7 +57,9 @@ class PrimitiveCompanionLowering(val context: JsIrBackendContext) : BodyLowering
|
|||||||
p.setter?.let { if (it.name == function.name) return it }
|
p.setter?.let { if (it.name == function.name) return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
error("Accessor not found")
|
return actualCompanion.declarations
|
||||||
|
.filterIsInstance<IrSimpleFunction>()
|
||||||
|
.single { it.name == function.name }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
|
|||||||
+1
-7
@@ -22,13 +22,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import java.lang.IllegalArgumentException
|
import java.lang.IllegalArgumentException
|
||||||
|
|
||||||
val scriptRemoveReceiverLowering = makeIrModulePhase(
|
class ScriptRemoveReceiverLowering(val context: CommonBackendContext) : FileLoweringPass {
|
||||||
::ScriptRemoveReceiverLowering,
|
|
||||||
name = "ScriptRemoveReceiver",
|
|
||||||
description = "Remove receivers for declarations in script"
|
|
||||||
)
|
|
||||||
|
|
||||||
private class ScriptRemoveReceiverLowering(val context: CommonBackendContext) : FileLoweringPass {
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
if (context.scriptMode) {
|
if (context.scriptMode) {
|
||||||
irFile.declarations.transformFlat {
|
irFile.declarations.transformFlat {
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
|||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
fun generateTests(context: JsIrBackendContext, moduleFragment: IrModuleFragment) {
|
||||||
|
val generator = TestGenerator(context)
|
||||||
|
|
||||||
|
moduleFragment.files.forEach {
|
||||||
|
generator.lower(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TestGenerator(val context: JsIrBackendContext) : FileLoweringPass {
|
class TestGenerator(val context: JsIrBackendContext) : FileLoweringPass {
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsBlock, JsGenera
|
|||||||
val fileContext = data.newDeclaration()
|
val fileContext = data.newDeclaration()
|
||||||
val block = JsGlobalBlock()
|
val block = JsGlobalBlock()
|
||||||
|
|
||||||
declaration.declarations.forEach {
|
ArrayList(declaration.declarations).forEach {
|
||||||
block.statements.add(it.accept(IrDeclarationToJsTransformer(), fileContext))
|
block.statements.add(it.accept(IrDeclarationToJsTransformer(), fileContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -50,17 +50,21 @@ class IrModuleToJsTransformer(
|
|||||||
|
|
||||||
namer.merge(module.files, additionalPackages)
|
namer.merge(module.files, additionalPackages)
|
||||||
|
|
||||||
val jsCode = if (fullJs) generateWrappedModuleBody(module, exportedModule) else null
|
val jsCode = if (fullJs) generateWrappedModuleBody(module, exportedModule, namer) else null
|
||||||
|
|
||||||
val dceJsCode = if (dceJs) {
|
val dceJsCode = if (dceJs) {
|
||||||
eliminateDeadDeclarations(module, backendContext, mainFunction)
|
eliminateDeadDeclarations(module, backendContext, mainFunction)
|
||||||
generateWrappedModuleBody(module, exportedModule)
|
// Use a fresh namer for DCE so that we could compare the result with DCE-driven
|
||||||
|
// TODO: is this mode relevant for scripting? If yes, refactor so that the external name tables are used here when needed.
|
||||||
|
val namer = NameTables(emptyList())
|
||||||
|
namer.merge(module.files, additionalPackages)
|
||||||
|
generateWrappedModuleBody(module, exportedModule, namer)
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
return CompilerResult(jsCode, dceJsCode, dts)
|
return CompilerResult(jsCode, dceJsCode, dts)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateWrappedModuleBody(module: IrModuleFragment, exportedModule: ExportedModule): String {
|
private fun generateWrappedModuleBody(module: IrModuleFragment, exportedModule: ExportedModule, namer: NameTables): String {
|
||||||
val program = JsProgram()
|
val program = JsProgram()
|
||||||
|
|
||||||
val nameGenerator = IrNamerImpl(
|
val nameGenerator = IrNamerImpl(
|
||||||
|
|||||||
@@ -199,7 +199,8 @@ class NameTables(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (p in packages) {
|
for (p in packages) {
|
||||||
for (declaration in p.declarations) {
|
// TODO
|
||||||
|
for (declaration in ArrayList(p.declarations)) {
|
||||||
acceptDeclaration(declaration)
|
acceptDeclaration(declaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,6 +333,10 @@ class NameTables(
|
|||||||
val signature = fieldSignature(field)
|
val signature = fieldSignature(field)
|
||||||
val name = memberNames.names[signature] ?: mappedNames[mapToKey(signature)]
|
val name = memberNames.names[signature] ?: mappedNames[mapToKey(signature)]
|
||||||
|
|
||||||
|
if (name == null) {
|
||||||
|
return sanitizeName(field.name.asString()) + "__error"
|
||||||
|
}
|
||||||
|
|
||||||
require(name != null) {
|
require(name != null) {
|
||||||
"Can't find name for member field ${field.render()}"
|
"Can't find name for member field ${field.render()}"
|
||||||
}
|
}
|
||||||
@@ -346,6 +351,11 @@ class NameTables(
|
|||||||
// of `invoke` functions in FunctionN interfaces
|
// of `invoke` functions in FunctionN interfaces
|
||||||
if (name == null && signature is ParameterTypeBasedSignature && signature.suggestedName.startsWith("invoke"))
|
if (name == null && signature is ParameterTypeBasedSignature && signature.suggestedName.startsWith("invoke"))
|
||||||
return signature.suggestedName
|
return signature.suggestedName
|
||||||
|
|
||||||
|
if (name == null) {
|
||||||
|
return sanitizeName(function.name.asString()) + "__error" // TODO one case is a virtual method of an abstract class with no implementation
|
||||||
|
}
|
||||||
|
|
||||||
require(name != null) {
|
require(name != null) {
|
||||||
"Can't find name for member function ${function.render()}"
|
"Can't find name for member function ${function.render()}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.ir.builders.irNull
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
@@ -60,6 +59,9 @@ class JvmBackendContext(
|
|||||||
) : CommonBackendContext {
|
) : CommonBackendContext {
|
||||||
override val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
|
override val transformedFunction: MutableMap<IrFunctionSymbol, IrSimpleFunctionSymbol>
|
||||||
get() = TODO("not implemented")
|
get() = TODO("not implemented")
|
||||||
|
|
||||||
|
override val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
|
||||||
|
|
||||||
override val scriptMode: Boolean = false
|
override val scriptMode: Boolean = false
|
||||||
override val lateinitNullableFields = mutableMapOf<IrField, IrField>()
|
override val lateinitNullableFields = mutableMapOf<IrField, IrField>()
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.UniqId
|
import org.jetbrains.kotlin.ir.util.UniqId
|
||||||
@@ -41,6 +41,7 @@ class WasmBackendContext(
|
|||||||
override val scriptMode = false
|
override val scriptMode = false
|
||||||
override val transformedFunction = mutableMapOf<IrFunctionSymbol, IrSimpleFunctionSymbol>()
|
override val transformedFunction = mutableMapOf<IrFunctionSymbol, IrSimpleFunctionSymbol>()
|
||||||
override val lateinitNullableFields = mutableMapOf<IrField, IrField>()
|
override val lateinitNullableFields = mutableMapOf<IrField, IrField>()
|
||||||
|
override val extractedLocalClasses: MutableSet<IrClass> = hashSetOf()
|
||||||
|
|
||||||
// Place to store declarations excluded from code generation
|
// Place to store declarations excluded from code generation
|
||||||
val excludedDeclarations: IrPackageFragment by lazy {
|
val excludedDeclarations: IrPackageFragment by lazy {
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ interface StageController {
|
|||||||
|
|
||||||
fun <T> withInitialIr(block: () -> T): T = block()
|
fun <T> withInitialIr(block: () -> T): T = block()
|
||||||
|
|
||||||
fun <T> withInitialStateOf(declaration: IrDeclaration, block: () -> T): T = block()
|
|
||||||
|
|
||||||
fun <T> restrictTo(declaration: IrDeclaration, fn: () -> T): T = fn()
|
fun <T> restrictTo(declaration: IrDeclaration, fn: () -> T): T = fn()
|
||||||
|
|
||||||
fun <T> bodyLowering(fn: () -> T): T = fn()
|
fun <T> bodyLowering(fn: () -> T): T = fn()
|
||||||
@@ -38,6 +36,7 @@ interface StageController {
|
|||||||
fun canAccessDeclarationsOf(irClass: IrClass): Boolean = true
|
fun canAccessDeclarationsOf(irClass: IrClass): Boolean = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <T> withInitialIr(noinline fn: () -> T): T {
|
inline fun <T> withInitialIr(noinline fn: () -> T): T {
|
||||||
return stageController.withInitialIr(fn)
|
return stageController.withInitialIr(fn)
|
||||||
}
|
}
|
||||||
+1
@@ -6,6 +6,7 @@ where advanced options include:
|
|||||||
-Xgenerate-dts Generate TypeScript declarations .d.ts file alongside JS file. Available in IR backend only.
|
-Xgenerate-dts Generate TypeScript declarations .d.ts file alongside JS file. Available in IR backend only.
|
||||||
-Xinclude=<path> A path to an intermediate library that should be processed in the same manner as source files.
|
-Xinclude=<path> A path to an intermediate library that should be processed in the same manner as source files.
|
||||||
-Xir-dce Perform experimental dead code elimination
|
-Xir-dce Perform experimental dead code elimination
|
||||||
|
-Xir-dce-driven Perform a more experimental faster dead code elimination
|
||||||
-Xir-only Disables pre-IR backend
|
-Xir-only Disables pre-IR backend
|
||||||
-Xir-produce-js Generates JS file using IR backend. Also disables pre-IR backend
|
-Xir-produce-js Generates JS file using IR backend. Also disables pre-IR backend
|
||||||
-Xir-produce-klib-dir Generate unpacked KLIB into parent directory of output JS file.
|
-Xir-produce-klib-dir Generate unpacked KLIB into parent directory of output JS file.
|
||||||
|
|||||||
@@ -133,6 +133,12 @@ projectTest("jsTest", true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
projectTest("jsIrTest", true) {
|
projectTest("jsIrTest", true) {
|
||||||
|
systemProperty("kotlin.js.ir.pir", "false")
|
||||||
|
setUpJsBoxTests(jsEnabled = false, jsIrEnabled = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
projectTest("jsPirTest", true) {
|
||||||
|
systemProperty("kotlin.js.ir.skipRegularMode", "true")
|
||||||
setUpJsBoxTests(jsEnabled = false, jsIrEnabled = true)
|
setUpJsBoxTests(jsEnabled = false, jsIrEnabled = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,13 +81,17 @@ abstract class BasicBoxTest(
|
|||||||
|
|
||||||
private val testGroupOutputDirForCompilation = File(pathToRootOutputDir + "out/" + testGroupOutputDirPrefix)
|
private val testGroupOutputDirForCompilation = File(pathToRootOutputDir + "out/" + testGroupOutputDirPrefix)
|
||||||
private val testGroupOutputDirForMinification = File(pathToRootOutputDir + "out-min/" + testGroupOutputDirPrefix)
|
private val testGroupOutputDirForMinification = File(pathToRootOutputDir + "out-min/" + testGroupOutputDirPrefix)
|
||||||
|
private val testGroupOutputDirForPir = File(pathToRootOutputDir + "out-pir/" + testGroupOutputDirPrefix)
|
||||||
|
|
||||||
protected open fun getOutputPrefixFile(testFilePath: String): File? = null
|
protected open fun getOutputPrefixFile(testFilePath: String): File? = null
|
||||||
protected open fun getOutputPostfixFile(testFilePath: String): File? = null
|
protected open fun getOutputPostfixFile(testFilePath: String): File? = null
|
||||||
|
|
||||||
protected open val runMinifierByDefault: Boolean = false
|
protected open val runMinifierByDefault: Boolean = false
|
||||||
protected open val skipMinification = getBoolean("kotlin.js.skipMinificationTest")
|
protected open val skipMinification = getBoolean("kotlin.js.skipMinificationTest")
|
||||||
|
|
||||||
|
protected open val skipRegularMode: Boolean = false
|
||||||
protected open val runIrDce: Boolean = false
|
protected open val runIrDce: Boolean = false
|
||||||
|
protected open val runIrPir: Boolean = false
|
||||||
|
|
||||||
protected open val incrementalCompilationChecksEnabled = true
|
protected open val incrementalCompilationChecksEnabled = true
|
||||||
|
|
||||||
@@ -105,6 +109,7 @@ abstract class BasicBoxTest(
|
|||||||
val file = File(filePath)
|
val file = File(filePath)
|
||||||
val outputDir = getOutputDir(file)
|
val outputDir = getOutputDir(file)
|
||||||
val dceOutputDir = getOutputDir(file, testGroupOutputDirForMinification)
|
val dceOutputDir = getOutputDir(file, testGroupOutputDirForMinification)
|
||||||
|
val pirOutputDir = getOutputDir(file, testGroupOutputDirForPir)
|
||||||
var fileContent = KotlinTestUtils.doLoadFile(file)
|
var fileContent = KotlinTestUtils.doLoadFile(file)
|
||||||
if (coroutinesPackage.isNotEmpty()) {
|
if (coroutinesPackage.isNotEmpty()) {
|
||||||
fileContent = fileContent.replace("COROUTINES_PACKAGE", coroutinesPackage)
|
fileContent = fileContent.replace("COROUTINES_PACKAGE", coroutinesPackage)
|
||||||
@@ -158,10 +163,11 @@ abstract class BasicBoxTest(
|
|||||||
|
|
||||||
val outputFileName = module.outputFileName(outputDir) + ".js"
|
val outputFileName = module.outputFileName(outputDir) + ".js"
|
||||||
val dceOutputFileName = module.outputFileName(dceOutputDir) + ".js"
|
val dceOutputFileName = module.outputFileName(dceOutputDir) + ".js"
|
||||||
|
val pirOutputFileName = module.outputFileName(pirOutputDir) + ".js"
|
||||||
val isMainModule = mainModuleName == module.name
|
val isMainModule = mainModuleName == module.name
|
||||||
generateJavaScriptFile(
|
generateJavaScriptFile(
|
||||||
testFactory.tmpDir,
|
testFactory.tmpDir,
|
||||||
file.parent, module, outputFileName, dceOutputFileName, dependencies, allDependencies, friends, modules.size > 1,
|
file.parent, module, outputFileName, dceOutputFileName, pirOutputFileName, dependencies, allDependencies, friends, modules.size > 1,
|
||||||
!SKIP_SOURCEMAP_REMAPPING.matcher(fileContent).find(), outputPrefixFile, outputPostfixFile,
|
!SKIP_SOURCEMAP_REMAPPING.matcher(fileContent).find(), outputPrefixFile, outputPostfixFile,
|
||||||
actualMainCallParameters, testPackage, testFunction, needsFullIrRuntime, isMainModule, klibBasedMpp
|
actualMainCallParameters, testPackage, testFunction, needsFullIrRuntime, isMainModule, klibBasedMpp
|
||||||
)
|
)
|
||||||
@@ -219,6 +225,10 @@ abstract class BasicBoxTest(
|
|||||||
val dceAllJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map { it.first.replace(outputDir.absolutePath, dceOutputDir.absolutePath) } +
|
val dceAllJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map { it.first.replace(outputDir.absolutePath, dceOutputDir.absolutePath) } +
|
||||||
globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles
|
globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles
|
||||||
|
|
||||||
|
val pirAllJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map { it.first.replace(outputDir.absolutePath, pirOutputDir.absolutePath) } +
|
||||||
|
globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles
|
||||||
|
|
||||||
|
|
||||||
val dontRunGeneratedCode = InTextDirectivesUtils.dontRunGeneratedCode(targetBackend, file)
|
val dontRunGeneratedCode = InTextDirectivesUtils.dontRunGeneratedCode(targetBackend, file)
|
||||||
|
|
||||||
if (!dontRunGeneratedCode && generateNodeJsRunner && !SKIP_NODE_JS.matcher(fileContent).find()) {
|
if (!dontRunGeneratedCode && generateNodeJsRunner && !SKIP_NODE_JS.matcher(fileContent).find()) {
|
||||||
@@ -229,10 +239,16 @@ abstract class BasicBoxTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dontRunGeneratedCode) {
|
if (!dontRunGeneratedCode) {
|
||||||
runGeneratedCode(allJsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
|
if (!skipRegularMode) {
|
||||||
|
runGeneratedCode(allJsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
|
||||||
|
|
||||||
if (runIrDce) {
|
if (runIrDce) {
|
||||||
runGeneratedCode(dceAllJsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
|
runGeneratedCode(dceAllJsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runIrPir && !SKIP_DCE_DRIVEN.matcher(fileContent).find()) {
|
||||||
|
runGeneratedCode(pirAllJsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,6 +368,7 @@ abstract class BasicBoxTest(
|
|||||||
module: TestModule,
|
module: TestModule,
|
||||||
outputFileName: String,
|
outputFileName: String,
|
||||||
dceOutputFileName: String,
|
dceOutputFileName: String,
|
||||||
|
pirOutputFileName: String,
|
||||||
dependencies: List<String>,
|
dependencies: List<String>,
|
||||||
allDependencies: List<String>,
|
allDependencies: List<String>,
|
||||||
friends: List<String>,
|
friends: List<String>,
|
||||||
@@ -383,10 +400,11 @@ abstract class BasicBoxTest(
|
|||||||
val config = createConfig(sourceDirs, module, dependencies, allDependencies, friends, multiModule, tmpDir, incrementalData = null, klibBasedMpp = klibBasedMpp)
|
val config = createConfig(sourceDirs, module, dependencies, allDependencies, friends, multiModule, tmpDir, incrementalData = null, klibBasedMpp = klibBasedMpp)
|
||||||
val outputFile = File(outputFileName)
|
val outputFile = File(outputFileName)
|
||||||
val dceOutputFile = File(dceOutputFileName)
|
val dceOutputFile = File(dceOutputFileName)
|
||||||
|
val pirOutputFile = File(pirOutputFileName)
|
||||||
|
|
||||||
val incrementalData = IncrementalData()
|
val incrementalData = IncrementalData()
|
||||||
translateFiles(
|
translateFiles(
|
||||||
psiFiles.map(TranslationUnit::SourceFile), outputFile, dceOutputFile, config, outputPrefixFile, outputPostfixFile,
|
psiFiles.map(TranslationUnit::SourceFile), outputFile, dceOutputFile, pirOutputFile, config, outputPrefixFile, outputPostfixFile,
|
||||||
mainCallParameters, incrementalData, remap, testPackage, testFunction, needsFullIrRuntime, isMainModule
|
mainCallParameters, incrementalData, remap, testPackage, testFunction, needsFullIrRuntime, isMainModule
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -438,7 +456,7 @@ abstract class BasicBoxTest(
|
|||||||
val recompiledOutputFile = File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js")
|
val recompiledOutputFile = File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js")
|
||||||
|
|
||||||
translateFiles(
|
translateFiles(
|
||||||
translationUnits, recompiledOutputFile, recompiledOutputFile, recompiledConfig, outputPrefixFile, outputPostfixFile,
|
translationUnits, recompiledOutputFile, recompiledOutputFile, recompiledOutputFile, recompiledConfig, outputPrefixFile, outputPostfixFile,
|
||||||
mainCallParameters, incrementalData, remap, testPackage, testFunction, needsFullIrRuntime, false
|
mainCallParameters, incrementalData, remap, testPackage, testFunction, needsFullIrRuntime, false
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -501,6 +519,7 @@ abstract class BasicBoxTest(
|
|||||||
units: List<TranslationUnit>,
|
units: List<TranslationUnit>,
|
||||||
outputFile: File,
|
outputFile: File,
|
||||||
dceOutputFile: File,
|
dceOutputFile: File,
|
||||||
|
pirOutputFile: File,
|
||||||
config: JsConfig,
|
config: JsConfig,
|
||||||
outputPrefixFile: File?,
|
outputPrefixFile: File?,
|
||||||
outputPostfixFile: File?,
|
outputPostfixFile: File?,
|
||||||
@@ -895,6 +914,7 @@ abstract class BasicBoxTest(
|
|||||||
private val CALL_MAIN_PATTERN = Pattern.compile("^// *CALL_MAIN *$", Pattern.MULTILINE)
|
private val CALL_MAIN_PATTERN = Pattern.compile("^// *CALL_MAIN *$", Pattern.MULTILINE)
|
||||||
private val KJS_WITH_FULL_RUNTIME = Pattern.compile("^// *KJS_WITH_FULL_RUNTIME *\$", Pattern.MULTILINE)
|
private val KJS_WITH_FULL_RUNTIME = Pattern.compile("^// *KJS_WITH_FULL_RUNTIME *\$", Pattern.MULTILINE)
|
||||||
private val KLIB_BASED_MPP = Pattern.compile("^// KLIB_BASED_MPP *$", Pattern.MULTILINE)
|
private val KLIB_BASED_MPP = Pattern.compile("^// KLIB_BASED_MPP *$", Pattern.MULTILINE)
|
||||||
|
private val SKIP_DCE_DRIVEN = Pattern.compile("^// *SKIP_DCE_DRIVEN *$", Pattern.MULTILINE)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
protected val runTestInNashorn = getBoolean("kotlin.js.useNashorn")
|
protected val runTestInNashorn = getBoolean("kotlin.js.useNashorn")
|
||||||
|
|||||||
@@ -44,7 +44,13 @@ abstract class BasicIrBoxTest(
|
|||||||
|
|
||||||
override val skipMinification = true
|
override val skipMinification = true
|
||||||
|
|
||||||
override val runIrDce: Boolean = true
|
private fun getBoolean(s: String, default: Boolean) = System.getProperty(s)?.let { getBoolean(it) } ?: default
|
||||||
|
|
||||||
|
override val skipRegularMode: Boolean = getBoolean("kotlin.js.ir.skipRegularMode")
|
||||||
|
|
||||||
|
override val runIrDce: Boolean = getBoolean("kotlin.js.ir.dce", true)
|
||||||
|
|
||||||
|
override val runIrPir: Boolean = getBoolean("kotlin.js.ir.pir", true)
|
||||||
|
|
||||||
// TODO Design incremental compilation for IR and add test support
|
// TODO Design incremental compilation for IR and add test support
|
||||||
override val incrementalCompilationChecksEnabled = false
|
override val incrementalCompilationChecksEnabled = false
|
||||||
@@ -63,6 +69,7 @@ abstract class BasicIrBoxTest(
|
|||||||
units: List<TranslationUnit>,
|
units: List<TranslationUnit>,
|
||||||
outputFile: File,
|
outputFile: File,
|
||||||
dceOutputFile: File,
|
dceOutputFile: File,
|
||||||
|
pirOutputFile: File,
|
||||||
config: JsConfig,
|
config: JsConfig,
|
||||||
outputPrefixFile: File?,
|
outputPrefixFile: File?,
|
||||||
outputPostfixFile: File?,
|
outputPostfixFile: File?,
|
||||||
@@ -111,33 +118,54 @@ abstract class BasicIrBoxTest(
|
|||||||
PhaseConfig(jsPhases)
|
PhaseConfig(jsPhases)
|
||||||
}
|
}
|
||||||
|
|
||||||
val compiledModule = compile(
|
if (!skipRegularMode) {
|
||||||
project = config.project,
|
val compiledModule = compile(
|
||||||
mainModule = MainModule.SourceFiles(filesToCompile),
|
project = config.project,
|
||||||
analyzer = AnalyzerWithCompilerReport(config.configuration),
|
mainModule = MainModule.SourceFiles(filesToCompile),
|
||||||
configuration = config.configuration,
|
analyzer = AnalyzerWithCompilerReport(config.configuration),
|
||||||
phaseConfig = phaseConfig,
|
configuration = config.configuration,
|
||||||
allDependencies = resolvedLibraries,
|
phaseConfig = phaseConfig,
|
||||||
friendDependencies = emptyList(),
|
allDependencies = resolvedLibraries,
|
||||||
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
|
friendDependencies = emptyList(),
|
||||||
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))),
|
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
|
||||||
generateFullJs = true,
|
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))),
|
||||||
generateDceJs = runIrDce
|
generateFullJs = true,
|
||||||
)
|
generateDceJs = runIrDce
|
||||||
|
)
|
||||||
|
|
||||||
val wrappedCode = wrapWithModuleEmulationMarkers(compiledModule.jsCode!!, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
val wrappedCode =
|
||||||
outputFile.write(wrappedCode)
|
wrapWithModuleEmulationMarkers(compiledModule.jsCode!!, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
||||||
|
outputFile.write(wrappedCode)
|
||||||
|
|
||||||
compiledModule.dceJsCode?.let { dceJsCode ->
|
compiledModule.dceJsCode?.let { dceJsCode ->
|
||||||
val dceWrappedCode = wrapWithModuleEmulationMarkers(dceJsCode, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
val dceWrappedCode =
|
||||||
dceOutputFile.write(dceWrappedCode)
|
wrapWithModuleEmulationMarkers(dceJsCode, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
||||||
|
dceOutputFile.write(dceWrappedCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generateDts) {
|
||||||
|
val dtsFile = outputFile.withReplacedExtensionOrNull("_v5.js", ".d.ts")
|
||||||
|
dtsFile?.write(compiledModule.tsDefinitions ?: error("No ts definitions"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generateDts) {
|
if (runIrPir) {
|
||||||
val dtsFile = outputFile.withReplacedExtensionOrNull("_v5.js", ".d.ts")
|
compile(
|
||||||
dtsFile?.write(compiledModule.tsDefinitions ?: error("No ts definitions"))
|
project = config.project,
|
||||||
|
mainModule = MainModule.SourceFiles(filesToCompile),
|
||||||
|
analyzer = AnalyzerWithCompilerReport(config.configuration),
|
||||||
|
configuration = config.configuration,
|
||||||
|
phaseConfig = phaseConfig,
|
||||||
|
allDependencies = resolvedLibraries,
|
||||||
|
friendDependencies = emptyList(),
|
||||||
|
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
|
||||||
|
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))),
|
||||||
|
dceDriven = true
|
||||||
|
).jsCode!!.let { pirCode ->
|
||||||
|
val pirWrappedCode = wrapWithModuleEmulationMarkers(pirCode, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
||||||
|
pirOutputFile.write(pirWrappedCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
generateKLib(
|
generateKLib(
|
||||||
project = config.project,
|
project = config.project,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// TARGET_BACKEND: JS_IR
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// SKIP_DCE_DRIVEN
|
||||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||||
// RUN_PLAIN_BOX_FUNCTION
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user