BlockDecomposerLowering

This commit is contained in:
Anton Bannykh
2019-12-24 23:03:13 +03:00
committed by Anton Bannykh
parent e2d16d5096
commit 9812291364
2 changed files with 45 additions and 59 deletions
@@ -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)
@@ -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(