BlockDecomposerLowering
This commit is contained in:
committed by
Anton Bannykh
parent
e2d16d5096
commit
9812291364
@@ -383,11 +383,8 @@ private val autoboxingTransformerPhase = makeJsModulePhase(
|
||||
description = "Insert box/unbox intrinsics"
|
||||
)
|
||||
|
||||
private val blockDecomposerLoweringPhase = makeCustomJsModulePhase(
|
||||
{ context, module ->
|
||||
JsBlockDecomposerLowering(context).lower(module)
|
||||
module.patchDeclarationParents()
|
||||
},
|
||||
private val blockDecomposerLoweringPhase = makeJsModulePhase(
|
||||
::JsBlockDecomposerLowering,
|
||||
name = "BlockDecomposerLowering",
|
||||
description = "Transform statement-like-expression nodes into pure-statement to make it easily transform into JS",
|
||||
prerequisite = setOf(typeOperatorLoweringPhase, suspendFunctionsLoweringPhase)
|
||||
|
||||
+43
-54
@@ -5,8 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -30,31 +32,54 @@ class JsBlockDecomposerLowering(val context: JsIrBackendContext) : AbstractBlock
|
||||
JsIrBuilder.buildCall(context.intrinsics.unreachable.symbol, context.irBuiltIns.nothingType)
|
||||
}
|
||||
|
||||
abstract class AbstractBlockDecomposerLowering(context: CommonBackendContext) : DeclarationContainerLoweringPass {
|
||||
abstract class AbstractBlockDecomposerLowering(
|
||||
context: CommonBackendContext
|
||||
) : BodyLoweringPass {
|
||||
|
||||
private val nothingType = context.irBuiltIns.nothingType
|
||||
|
||||
// Expression with Nothing type to be inserted in places of unreachable expression
|
||||
abstract fun unreachableExpression(): IrExpression
|
||||
|
||||
private val decomposerTransformer = BlockDecomposerTransformer(context, ::unreachableExpression)
|
||||
private val nothingType = context.irBuiltIns.nothingType
|
||||
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
irDeclarationContainer.transformDeclarationsFlat { declaration ->
|
||||
when (declaration) {
|
||||
is IrScript -> {
|
||||
lower(declaration)
|
||||
listOf(declaration)
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
when (container) {
|
||||
is IrFunction -> {
|
||||
container.accept(decomposerTransformer, null)
|
||||
irBody.patchDeclarationParents(container)
|
||||
}
|
||||
is IrField -> {
|
||||
container.initializer?.apply {
|
||||
|
||||
val initFunction = JsIrBuilder.buildFunction(
|
||||
container.name.asString() + "\$init\$",
|
||||
container.type,
|
||||
container.parent,
|
||||
Visibilities.PRIVATE
|
||||
)
|
||||
|
||||
val newBody = toBlockBody(initFunction)
|
||||
newBody.patchDeclarationParents(initFunction)
|
||||
initFunction.body = newBody
|
||||
|
||||
initFunction.accept(decomposerTransformer, null)
|
||||
|
||||
val lastStatement = newBody.statements.last()
|
||||
val actualParent = if (newBody.statements.size > 1 || lastStatement !is IrReturn || lastStatement.value != expression) {
|
||||
expression = JsIrBuilder.buildCall(initFunction.symbol, expression.type)
|
||||
(container.parent as IrDeclarationContainer).declarations += initFunction
|
||||
initFunction
|
||||
} else {
|
||||
container
|
||||
}
|
||||
|
||||
patchDeclarationParents(actualParent)
|
||||
}
|
||||
is IrFunction -> {
|
||||
lower(declaration)
|
||||
listOf(declaration)
|
||||
}
|
||||
is IrField -> lower(declaration, irDeclarationContainer)
|
||||
else -> listOf(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
irDeclarationContainer.transformChildrenVoid(CodeCleaner())
|
||||
// irDeclarationContainer.transformChildrenVoid(CodeCleaner()) TODO
|
||||
}
|
||||
|
||||
private inner class CodeCleaner : IrElementTransformerVoid() {
|
||||
@@ -98,49 +123,13 @@ abstract class AbstractBlockDecomposerLowering(context: CommonBackendContext) :
|
||||
}
|
||||
}
|
||||
|
||||
fun lower(irScript: IrScript) {
|
||||
irScript.transform(decomposerTransformer, null)
|
||||
}
|
||||
|
||||
fun lower(irFunction: IrFunction) {
|
||||
(irFunction.body as? IrExpressionBody)?.apply {
|
||||
irFunction.body = toBlockBody(irFunction)
|
||||
}
|
||||
irFunction.accept(decomposerTransformer, null)
|
||||
}
|
||||
|
||||
private fun IrExpressionBody.toBlockBody(containingFunction: IrFunction): IrBlockBody {
|
||||
expression.patchDeclarationParents(containingFunction)
|
||||
val returnStatement = JsIrBuilder.buildReturn(containingFunction.symbol, expression, nothingType)
|
||||
return IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply {
|
||||
return IrBlockBodyImpl(startOffset, endOffset) {
|
||||
expression.patchDeclarationParents(containingFunction)
|
||||
val returnStatement = JsIrBuilder.buildReturn(containingFunction.symbol, expression, nothingType)
|
||||
statements += returnStatement
|
||||
}
|
||||
}
|
||||
|
||||
fun lower(irField: IrField, container: IrDeclarationContainer): List<IrDeclaration> {
|
||||
irField.initializer?.apply {
|
||||
val initFunction = JsIrBuilder.buildFunction(
|
||||
irField.name.asString() + "\$init\$",
|
||||
expression.type,
|
||||
container,
|
||||
Visibilities.PRIVATE
|
||||
)
|
||||
|
||||
val newBody = toBlockBody(initFunction)
|
||||
newBody.patchDeclarationParents(initFunction)
|
||||
initFunction.body = newBody
|
||||
|
||||
lower(initFunction)
|
||||
|
||||
val lastStatement = newBody.statements.last()
|
||||
if (newBody.statements.size > 1 || lastStatement !is IrReturn || lastStatement.value != expression) {
|
||||
expression = JsIrBuilder.buildCall(initFunction.symbol, expression.type)
|
||||
return listOf(initFunction, irField)
|
||||
}
|
||||
}
|
||||
|
||||
return listOf(irField)
|
||||
}
|
||||
}
|
||||
|
||||
class BlockDecomposerTransformer(
|
||||
|
||||
Reference in New Issue
Block a user