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"
|
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)
|
||||||
|
|||||||
+43
-54
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user