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" description = "Insert box/unbox intrinsics"
) )
private val blockDecomposerLoweringPhase = makeCustomJsModulePhase( private val blockDecomposerLoweringPhase = makeJsModulePhase(
{ context, module -> ::JsBlockDecomposerLowering,
JsBlockDecomposerLowering(context).lower(module)
module.patchDeclarationParents()
},
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)
@@ -5,8 +5,10 @@
package org.jetbrains.kotlin.ir.backend.js.lower 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.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass 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.backend.common.ir.isElseBranch
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement 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) 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 // Expression with Nothing type to be inserted in places of unreachable expression
abstract fun unreachableExpression(): IrExpression abstract fun unreachableExpression(): IrExpression
private val decomposerTransformer = BlockDecomposerTransformer(context, ::unreachableExpression) private val decomposerTransformer = BlockDecomposerTransformer(context, ::unreachableExpression)
private val nothingType = context.irBuiltIns.nothingType
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irBody: IrBody, container: IrDeclaration) {
irDeclarationContainer.transformDeclarationsFlat { declaration -> when (container) {
when (declaration) { is IrFunction -> {
is IrScript -> { container.accept(decomposerTransformer, null)
lower(declaration) irBody.patchDeclarationParents(container)
listOf(declaration) }
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() { 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 { private fun IrExpressionBody.toBlockBody(containingFunction: IrFunction): IrBlockBody {
expression.patchDeclarationParents(containingFunction) return IrBlockBodyImpl(startOffset, endOffset) {
val returnStatement = JsIrBuilder.buildReturn(containingFunction.symbol, expression, nothingType) expression.patchDeclarationParents(containingFunction)
return IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply { val returnStatement = JsIrBuilder.buildReturn(containingFunction.symbol, expression, nothingType)
statements += returnStatement 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( class BlockDecomposerTransformer(