[JS IR BE] Remove conservative unit materialization
Remove UnitMaterializationLowering Remove Unit insertion in BridgeConstruction Fix codegen for when expressions without else branch
This commit is contained in:
-45
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.lower
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
|
||||||
import org.jetbrains.kotlin.ir.types.isUnit
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
|
|
||||||
class UnitMaterializationLowering(context: BackendContext) : FileLoweringPass {
|
|
||||||
|
|
||||||
private val unitType = context.irBuiltIns.unitType
|
|
||||||
private val unitValue
|
|
||||||
get() = IrGetObjectValueImpl(
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
unitType,
|
|
||||||
unitType.classifierOrFail as IrClassSymbol
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
return if (expression.type.isUnit()) expression.let {
|
|
||||||
IrCompositeImpl(it.startOffset, it.endOffset, it.type, it.origin, listOf(it, unitValue))
|
|
||||||
}
|
|
||||||
else expression
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -133,13 +133,6 @@ private val tailrecLoweringPhase = makeJsModulePhase(
|
|||||||
description = "Replace `tailrec` callsites with equivalent loop"
|
description = "Replace `tailrec` callsites with equivalent loop"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val unitMaterializationLoweringPhase = makeJsModulePhase(
|
|
||||||
::UnitMaterializationLowering,
|
|
||||||
name = "UnitMaterializationLowering",
|
|
||||||
description = "Insert Unit object where it is supposed to be",
|
|
||||||
prerequisite = setOf(tailrecLoweringPhase)
|
|
||||||
)
|
|
||||||
|
|
||||||
private val enumClassConstructorLoweringPhase = makeJsModulePhase(
|
private val enumClassConstructorLoweringPhase = makeJsModulePhase(
|
||||||
::EnumClassConstructorLowering,
|
::EnumClassConstructorLowering,
|
||||||
name = "EnumClassConstructorLowering",
|
name = "EnumClassConstructorLowering",
|
||||||
@@ -201,8 +194,7 @@ private val innerClassConstructorCallsLoweringPhase = makeJsModulePhase(
|
|||||||
private val suspendFunctionsLoweringPhase = makeJsModulePhase(
|
private val suspendFunctionsLoweringPhase = makeJsModulePhase(
|
||||||
::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"
|
||||||
prerequisite = setOf(unitMaterializationLoweringPhase)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private val privateMembersLoweringPhase = makeJsModulePhase(
|
private val privateMembersLoweringPhase = makeJsModulePhase(
|
||||||
@@ -389,7 +381,6 @@ val jsPhases = namedIrModulePhase(
|
|||||||
enumClassLoweringPhase then
|
enumClassLoweringPhase then
|
||||||
enumUsageLoweringPhase then
|
enumUsageLoweringPhase then
|
||||||
returnableBlockLoweringPhase then
|
returnableBlockLoweringPhase then
|
||||||
unitMaterializationLoweringPhase then
|
|
||||||
suspendFunctionsLoweringPhase then
|
suspendFunctionsLoweringPhase then
|
||||||
privateMembersLoweringPhase then
|
privateMembersLoweringPhase then
|
||||||
callableReferenceLoweringPhase then
|
callableReferenceLoweringPhase then
|
||||||
|
|||||||
+1
-14
@@ -105,8 +105,6 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val unitValue = JsIrBuilder.buildGetObjectValue(context.irBuiltIns.unitType, context.irBuiltIns.unitClass)
|
|
||||||
|
|
||||||
// Ported from from jvm.lower.BridgeLowering
|
// Ported from from jvm.lower.BridgeLowering
|
||||||
private fun createBridge(
|
private fun createBridge(
|
||||||
function: IrSimpleFunction,
|
function: IrSimpleFunction,
|
||||||
@@ -168,18 +166,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
|
|||||||
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
|
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is required for Unit materialization
|
+irReturn(call)
|
||||||
// TODO: generalize for boxed types and inline classes
|
|
||||||
// TODO: use return type in signature too
|
|
||||||
val returnValue = if (delegateTo.returnType.isUnit() && !function.returnType.isUnit()) {
|
|
||||||
irComposite(resultType = irFunction.returnType) {
|
|
||||||
+call
|
|
||||||
+unitValue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
call
|
|
||||||
}
|
|
||||||
+irReturn(returnValue)
|
|
||||||
}.apply {
|
}.apply {
|
||||||
irFunction.body = this
|
irFunction.body = this
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -5,12 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@@ -309,8 +311,16 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWhen(expression: IrWhen, context: JsGenerationContext): JsExpression {
|
override fun visitWhen(expression: IrWhen, context: JsGenerationContext): JsExpression {
|
||||||
// TODO check when w/o else branch and empty when
|
val lastBranch = expression.branches.lastOrNull()
|
||||||
return expression.toJsNode(this, context, ::JsConditional)!!
|
val implicitElse =
|
||||||
|
if (lastBranch == null || !isElseBranch(lastBranch))
|
||||||
|
JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(0))
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
assert(implicitElse == null || expression.type.isUnit()) { "Non unit when-expression must have else branch" }
|
||||||
|
|
||||||
|
return expression.toJsNode(this, context, ::JsConditional, implicitElse)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: JsGenerationContext): JsExpression {
|
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: JsGenerationContext): JsExpression {
|
||||||
|
|||||||
+3
-2
@@ -23,9 +23,10 @@ fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext
|
|||||||
fun <T : JsNode> IrWhen.toJsNode(
|
fun <T : JsNode> IrWhen.toJsNode(
|
||||||
tr: BaseIrElementToJsNodeTransformer<T, JsGenerationContext>,
|
tr: BaseIrElementToJsNodeTransformer<T, JsGenerationContext>,
|
||||||
data: JsGenerationContext,
|
data: JsGenerationContext,
|
||||||
node: (JsExpression, T, T?) -> T
|
node: (JsExpression, T, T?) -> T,
|
||||||
|
implicitElse: T? = null
|
||||||
): T? =
|
): T? =
|
||||||
branches.foldRight(null) { br, n ->
|
branches.foldRight(implicitElse) { br, n ->
|
||||||
val body = br.result.accept(tr, data)
|
val body = br.result.accept(tr, data)
|
||||||
if (isElseBranch(br)) body
|
if (isElseBranch(br)) body
|
||||||
else {
|
else {
|
||||||
|
|||||||
Reference in New Issue
Block a user