[JS IR BE] Eliminate identical IrElements duplicates

This commit is contained in:
Svyatoslav Kuzmich
2018-11-19 16:48:15 +03:00
parent ba0f652e02
commit 2172a12df4
10 changed files with 97 additions and 90 deletions
@@ -19,10 +19,16 @@ 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 {
class UnitMaterializationLowering(context: BackendContext) : FileLoweringPass {
private val unitType = context.irBuiltIns.unitType
private val unitValue = IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, unitType, unitType.classifierOrFail as IrClassSymbol)
private val unitValue
get() = IrGetObjectValueImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
unitType,
unitType.classifierOrFail as IrClassSymbol
)
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
@@ -79,19 +79,19 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine
}
}
class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransformerVoid() {
class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrElementTransformerVoid() {
private lateinit var function: IrFunction
private var tmpVarCounter: Int = 0
private val statementTransformer = StatementTransformer()
private val expressionTransformer = ExpressionTransformer()
private val constTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
private val constTrue get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
private val constFalse get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
private val nothingType = context.irBuiltIns.nothingNType
private val unitType = context.irBuiltIns.unitType
private val unitValue = JsIrBuilder.buildGetObjectValue(unitType, context.symbolTable.referenceClass(context.builtIns.unit))
private val unitValue get() = JsIrBuilder.buildGetObjectValue(unitType, context.symbolTable.referenceClass(context.builtIns.unit))
private val unreachableFunction = context.intrinsics.unreachable
private val booleanNotSymbol = context.irBuiltIns.booleanNotSymbol
@@ -43,9 +43,9 @@ data class CallableReferenceKey(
// TODO: generate $metadata$ property and fill it with corresponding KFunction/KProperty interface
class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KCALLABLE_NAME)
private val getterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_GET)
private val setterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_SET)
private val callableNameConst get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KCALLABLE_NAME)
private val getterConst get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_GET)
private val setterConst get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_SET)
private val callableToFactoryFunction = context.callableReferencesCache
private val newDeclarations = mutableListOf<IrDeclaration>()
@@ -327,13 +327,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
//
val cacheName = "${factoryFunction.name}_${Namer.KCALLABLE_CACHE_SUFFIX}"
val type = factoryFunction.returnType
val irNull = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType)
val cacheVar = JsIrBuilder.buildVar(type, factoryFunction.parent, cacheName, true, initializer = irNull)
val irNull = { JsIrBuilder.buildNull(context.irBuiltIns.nothingNType) }
val cacheVar = JsIrBuilder.buildVar(type, factoryFunction.parent, cacheName, true, initializer = irNull())
val irCacheValue = JsIrBuilder.buildGetValue(cacheVar.symbol)
val irCacheValue = { JsIrBuilder.buildGetValue(cacheVar.symbol) }
val irIfCondition = JsIrBuilder.buildCall(context.irBuiltIns.eqeqSymbol).apply {
putValueArgument(0, irCacheValue)
putValueArgument(1, irNull)
putValueArgument(0, irCacheValue())
putValueArgument(1, irNull())
}
val irSetCache =
JsIrBuilder.buildSetVariable(cacheVar.symbol, JsIrBuilder.buildGetValue(varSymbol), context.irBuiltIns.unitType)
@@ -344,7 +344,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
val irThenBranch = JsIrBuilder.buildBlock(context.irBuiltIns.unitType, thenStatements)
val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unitType, irIfCondition, irThenBranch)
statements += irIfNode
returnValue = irCacheValue
returnValue = irCacheValue()
returnStatements = listOf(cacheVar)
} else {
statements += bodyStatements
@@ -51,7 +51,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
*/
class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPass {
val litTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
val litTrue get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
val unitType = context.irBuiltIns.unitType
val nothingType = context.irBuiltIns.nothingType
@@ -70,7 +70,7 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
val commonType = mergeTypes(aTry.catches.map { it.catchParameter.type })
val pendingExceptionDeclaration = JsIrBuilder.buildVar(commonType, data, "\$p")
val pendingException = JsIrBuilder.buildGetValue(pendingExceptionDeclaration.symbol)
val pendingException = { JsIrBuilder.buildGetValue(pendingExceptionDeclaration.symbol) }
val branches = mutableListOf<IrBranch>()
@@ -81,9 +81,9 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
val typeSymbol = type.classifierOrNull
val castedPendingException = {
if (type !is IrDynamicType)
buildImplicitCast(pendingException, type, typeSymbol!!)
buildImplicitCast(pendingException(), type, typeSymbol!!)
else
pendingException
pendingException()
}
val catchBody = catch.result.transform(object : IrElementTransformer<IrValueSymbol> {
@@ -98,14 +98,14 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
branches += IrElseBranchImpl(catch.startOffset, catch.endOffset, litTrue, catchBody)
break
} else {
val typeCheck = buildIsCheck(pendingException, type, typeSymbol!!)
val typeCheck = buildIsCheck(pendingException(), type, typeSymbol!!)
branches += IrBranchImpl(catch.startOffset, catch.endOffset, typeCheck, catchBody)
}
}
if (commonType !is IrDynamicType) {
val throwStatement = JsIrBuilder.buildThrow(nothingType, pendingException)
val throwStatement = JsIrBuilder.buildThrow(nothingType, pendingException())
branches += IrElseBranchImpl(litTrue, JsIrBuilder.buildBlock(nothingType, listOf(throwStatement)))
}
@@ -40,9 +40,9 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
private val propertySetter = context.intrinsics.jsSetJSField.symbol
private val eqeqeqSymbol = context.irBuiltIns.eqeqSymbol
private val messageName = JsIrBuilder.buildString(stringType, "message")
private val causeName = JsIrBuilder.buildString(stringType, "cause")
private val nameName = JsIrBuilder.buildString(stringType, "name")
private val messageName get() = JsIrBuilder.buildString(stringType, "message")
private val causeName get() = JsIrBuilder.buildString(stringType, "cause")
private val nameName get() = JsIrBuilder.buildString(stringType, "name")
private val throwableClass = context.symbolTable.referenceClass(
context.getClass(JsIrBackendContext.KOTLIN_PACKAGE_FQN.child(Name.identifier("Throwable")))
@@ -121,15 +121,15 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
}
private fun extractConstructorParameters(expression: IrFunctionAccessExpression): Pair<IrExpression, IrExpression> {
val nullValue = IrConstImpl.constNull(expression.startOffset, expression.endOffset, nothingNType)
val nullValue = { IrConstImpl.constNull(expression.startOffset, expression.endOffset, nothingNType) }
return when {
expression.valueArgumentsCount == 0 -> Pair(nullValue, nullValue)
expression.valueArgumentsCount == 0 -> Pair(nullValue(), nullValue())
expression.valueArgumentsCount == 2 -> expression.run { Pair(getValueArgument(0)!!, getValueArgument(1)!!) }
else -> {
val arg = expression.getValueArgument(0)!!
when {
arg.type.makeNotNull().isThrowable() -> Pair(nullValue, arg)
else -> Pair(arg, nullValue)
arg.type.makeNotNull().isThrowable() -> Pair(nullValue(), arg)
else -> Pair(arg, nullValue())
}
}
}
@@ -229,7 +229,7 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
}
val klass = successor.klass
val receiver = IrGetValueImpl(expression.startOffset, expression.endOffset, klass.thisReceiver!!.symbol)
val receiver = { IrGetValueImpl(expression.startOffset, expression.endOffset, klass.thisReceiver!!.symbol) }
val fillStatements = fillThrowableInstance(expression, receiver, messageArg, causeArg)
@@ -240,21 +240,21 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
private fun fillThrowableInstance(
expression: IrFunctionAccessExpression,
receiver: IrExpression,
receiver: () -> IrExpression,
messageArg: IrExpression,
causeArg: IrExpression
): List<IrStatement> {
val setMessage = expression.run {
IrSetFieldImpl(startOffset, endOffset, successor.message.symbol, receiver, messageArg, unitType)
IrSetFieldImpl(startOffset, endOffset, successor.message.symbol, receiver(), messageArg, unitType)
}
val setCause = expression.run {
IrSetFieldImpl(startOffset, endOffset, successor.cause.symbol, receiver, causeArg, unitType)
IrSetFieldImpl(startOffset, endOffset, successor.cause.symbol, receiver(), causeArg, unitType)
}
val setStackTrace = IrCallImpl(expression.startOffset, expression.endOffset, unitType, captureStackFunction).apply {
putValueArgument(0, receiver)
putValueArgument(0, receiver())
}
return listOf(setMessage, setCause, setStackTrace)
@@ -264,10 +264,10 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
expression: IrFunctionAccessExpression,
parent: IrDeclarationParent
): Triple<IrExpression, IrExpression, List<IrStatement>> {
val nullValue = IrConstImpl.constNull(expression.startOffset, expression.endOffset, nothingNType)
val nullValue = { IrConstImpl.constNull(expression.startOffset, expression.endOffset, nothingNType) }
// Wrap parameters into variables to keep original evaluation order
return when {
expression.valueArgumentsCount == 0 -> Triple(nullValue, nullValue, emptyList())
expression.valueArgumentsCount == 0 -> Triple(nullValue(), nullValue(), emptyList())
expression.valueArgumentsCount == 2 -> {
val msg = expression.getValueArgument(0)!!
val cus = expression.getValueArgument(1)!!
@@ -276,7 +276,7 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
val check = JsIrBuilder.buildCall(eqeqeqSymbol, booleanType).apply {
putValueArgument(0, JsIrBuilder.buildGetValue(irValM.symbol))
putValueArgument(1, nullValue)
putValueArgument(1, nullValue())
}
val msgElvis = JsIrBuilder.buildIfElse(
@@ -292,7 +292,7 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
val argValue = JsIrBuilder.buildGetValue(irVal.symbol)
when {
arg.type.makeNotNull().isThrowable() -> Triple(safeCallToString(irVal), argValue, listOf(irVal))
else -> Triple(argValue, nullValue, listOf(irVal))
else -> Triple(argValue, nullValue(), listOf(irVal))
}
}
}
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
@@ -31,13 +32,13 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val unit = context.irBuiltIns.unitType
private val unitValue = JsIrBuilder.buildGetObjectValue(unit, unit.classifierOrFail as IrClassSymbol)
private val unitValue get() = JsIrBuilder.buildGetObjectValue(unit, unit.classifierOrFail as IrClassSymbol)
private val lit24 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 24)
private val lit16 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 16)
private val lit24 get() = JsIrBuilder.buildInt(context.irBuiltIns.intType, 24)
private val lit16 get() = JsIrBuilder.buildInt(context.irBuiltIns.intType, 16)
private val byteMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFF)
private val shortMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFFFF)
private val byteMask get() = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFF)
private val shortMask get() = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFFFF)
private val calculator = JsIrArithBuilder(context)
@@ -56,14 +57,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val typeOfIntrinsicSymbol = context.intrinsics.jsTypeOf.symbol
private val jsClassIntrinsicSymbol = context.intrinsics.jsClass
private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "string")
private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "boolean")
private val functionMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "function")
private val numberMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "number")
private val stringMarker get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, "string")
private val booleanMarker get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, "boolean")
private val functionMarker get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, "function")
private val numberMarker get() = JsIrBuilder.buildString(context.irBuiltIns.stringType, "number")
private val litTrue: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
private val litFalse: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
private val litNull: IrExpression = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType)
private val litTrue: IrExpression get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
private val litFalse: IrExpression get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
private val litNull: IrExpression get() = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType)
override fun lower(irFile: IrFile) {
irFile.transformChildren(object : IrElementTransformer<IrDeclarationParent> {
@@ -96,9 +97,9 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
val newStatements = mutableListOf<IrStatement>()
val argument = cacheValue(expression.argument, newStatements, declaration)
val irNullCheck = nullCheck(argument)
val irNullCheck = nullCheck(argument())
newStatements += JsIrBuilder.buildIfElse(expression.typeOperand, irNullCheck, JsIrBuilder.buildCall(throwNPE), argument)
newStatements += JsIrBuilder.buildIfElse(expression.typeOperand, irNullCheck, JsIrBuilder.buildCall(throwNPE), argument())
return expression.run { IrCompositeImpl(startOffset, endOffset, typeOperand, null, newStatements) }
}
@@ -117,12 +118,13 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
val newStatements = mutableListOf<IrStatement>()
val argument = cacheValue(expression.argument, newStatements, declaration)
val check = generateTypeCheck(argument, toType)
newStatements += JsIrBuilder.buildIfElse(toType, check, argument, failResult)
newStatements += JsIrBuilder.buildIfElse(toType, check, argument(), failResult)
return expression.run { IrCompositeImpl(startOffset, endOffset, toType, null, newStatements) }
return expression.run {
IrCompositeImpl(startOffset, endOffset, toType, null, newStatements)
}
}
private fun lowerImplicitCast(expression: IrTypeOperatorCall) = expression.run {
@@ -155,18 +157,19 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
assert((expression.operator == IrTypeOperator.NOT_INSTANCEOF) == inverted)
val toType = expression.typeOperand
val isCopyRequired = expression.argument.type.isNullable() && advancedCheckRequired(toType.makeNotNull())
val newStatements = mutableListOf<IrStatement>()
val argument =
if (isCopyRequired) cacheValue(expression.argument, newStatements, declaration) else expression.argument
val argument = cacheValue(expression.argument, newStatements, declaration)
val check = generateTypeCheck(argument, toType)
val result = if (inverted) calculator.not(check) else check
return if (isCopyRequired) {
newStatements += result
IrCompositeImpl(expression.startOffset, expression.endOffset, toType, null, newStatements)
} else result
newStatements += result
return IrCompositeImpl(
expression.startOffset,
expression.endOffset,
context.irBuiltIns.booleanType,
null,
newStatements
)
}
private fun nullCheck(value: IrExpression) = JsIrBuilder.buildCall(eqeq).apply {
@@ -178,40 +181,41 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
value: IrExpression,
newStatements: MutableList<IrStatement>,
declaration: IrDeclarationParent
): IrExpression {
): () -> IrExpressionWithCopy {
val varDeclaration = JsIrBuilder.buildVar(value.type, declaration, initializer = value)
newStatements += varDeclaration
return JsIrBuilder.buildGetValue(varDeclaration.symbol)
return { JsIrBuilder.buildGetValue(varDeclaration.symbol) }
}
private fun generateTypeCheck(argument: IrExpression, toType: IrType): IrExpression {
private fun generateTypeCheck(argument: () -> IrExpressionWithCopy, toType: IrType): IrExpression {
// TODO: Fix unbound symbols (in inline)
toType.classifierOrNull?.apply {
if (!isBound) {
return argument
return argument()
}
}
val toNotNullable = toType.makeNotNull()
val instanceCheck = generateTypeCheckNonNull(argument, toNotNullable)
val isFromNullable = argument.type.isNullable()
val argumentInstance = argument()
val instanceCheck = generateTypeCheckNonNull(argumentInstance, toNotNullable)
val isFromNullable = argumentInstance.type.isNullable()
val isToNullable = toType.isNullable()
val isNativeCheck = !advancedCheckRequired(toNotNullable)
return when {
!isFromNullable -> instanceCheck // ! -> *
isToNullable -> calculator.run { oror(nullCheck(argument), instanceCheck) } // * -> ?
isToNullable -> calculator.run { oror(nullCheck(argument()), instanceCheck) } // * -> ?
else -> if (isNativeCheck) instanceCheck else calculator.run {
andand(
not(nullCheck(argument)),
not(nullCheck(argument())),
instanceCheck
)
} // ? -> !
}
}
private fun generateTypeCheckNonNull(argument: IrExpression, toType: IrType): IrExpression {
private fun generateTypeCheckNonNull(argument: IrExpressionWithCopy, toType: IrType): IrExpression {
assert(!toType.isMarkedNullable())
return when {
toType.isAny() -> generateIsObjectCheck(argument)
@@ -232,7 +236,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
putValueArgument(0, argument)
}
private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: IrType): IrExpression {
private fun generateTypeCheckWithTypeParameter(argument: IrExpressionWithCopy, toType: IrType): IrExpression {
val typeParameterSymbol =
(toType.classifierOrNull as? IrTypeParameterSymbol) ?: error("expected type parameter, but $toType")
@@ -244,9 +248,8 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
val typeParameter = typeParameterSymbol.owner
assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
return typeParameter.superTypes.fold(litTrue) { r, t ->
val check = generateTypeCheckNonNull(argument, t.makeNotNull())
val check = generateTypeCheckNonNull(argument.copy(), t.makeNotNull())
calculator.and(r, check)
}
}
@@ -314,25 +317,23 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
val isNullable = expression.argument.type.isNullable()
val toType = expression.typeOperand
fun maskOp(arg: IrExpression, mask: IrExpression, shift: IrExpression) = calculator.run {
shr(shl(and(arg, mask), shift), shift)
fun maskOp(arg: IrExpression, mask: IrExpression, shift: IrExpressionWithCopy) = calculator.run {
shr(shl(and(arg, mask), shift), shift.copy())
}
val newStatements = mutableListOf<IrStatement>()
val argument =
if (isNullable) cacheValue(expression.argument, newStatements, declaration) else expression.argument
val argument = cacheValue(expression.argument, newStatements, declaration)
val casted = when {
toType.isByte() -> maskOp(argument, byteMask, lit24)
toType.isShort() -> maskOp(argument, shortMask, lit16)
toType.isByte() -> maskOp(argument(), byteMask, lit24)
toType.isShort() -> maskOp(argument(), shortMask, lit16)
toType.isLong() -> JsIrBuilder.buildCall(context.intrinsics.jsToLong).apply {
putValueArgument(0, argument)
putValueArgument(0, argument())
}
else -> error("Unreachable execution (coercion to non-Integer type")
}
newStatements += if (isNullable) JsIrBuilder.buildIfElse(toType, nullCheck(argument), litNull, casted) else casted
newStatements += if (isNullable) JsIrBuilder.buildIfElse(toType, nullCheck(argument()), litNull, casted) else casted
return expression.run { IrCompositeImpl(startOffset, endOffset, toType, null, newStatements) }
}
@@ -943,7 +943,7 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
}
}
function.transform(LiveLocalsTransformer(localToPropertyMap, JsIrBuilder.buildGetValue(thisReceiver), unit), null)
function.transform(LiveLocalsTransformer(localToPropertyMap, { JsIrBuilder.buildGetValue(thisReceiver) } , unit), null)
}
private fun computeLivenessAtSuspensionPoints(body: IrBody): Map<IrCall, List<IrValueDeclaration>> {
@@ -147,19 +147,19 @@ class SuspendedTerminatorsCollector(suspendableNodes: MutableSet<IrElement>) : S
class LiveLocalsTransformer(
private val localMap: Map<IrValueSymbol, IrFieldSymbol>,
private val receiver: IrExpression,
private val receiver: () -> IrExpression,
private val unitType: IrType
) :
IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
val field = localMap[expression.symbol] ?: return expression
return expression.run { IrGetFieldImpl(startOffset, endOffset, field, type, receiver, origin) }
return expression.run { IrGetFieldImpl(startOffset, endOffset, field, type, receiver(), origin) }
}
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
expression.transformChildrenVoid(this)
val field = localMap[expression.symbol] ?: return expression
return expression.run { IrSetFieldImpl(startOffset, endOffset, field, receiver, value, unitType, origin) }
return expression.run { IrSetFieldImpl(startOffset, endOffset, field, receiver(), value, unitType, origin) }
}
override fun visitVariable(declaration: IrVariable): IrStatement {
@@ -167,7 +167,7 @@ class LiveLocalsTransformer(
val field = localMap[declaration.symbol] ?: return declaration
val initializer = declaration.initializer
return if (initializer != null) {
declaration.run { IrSetFieldImpl(startOffset, endOffset, field, receiver, initializer, unitType) }
declaration.run { IrSetFieldImpl(startOffset, endOffset, field, receiver(), initializer, unitType) }
} else {
JsIrBuilder.buildComposite(declaration.type)
}
@@ -96,7 +96,7 @@ private class ReturnableBlockTransformer(
return super.visitDeclaration(declaration, data)
}
private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
private val constFalse get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
override fun visitContainerExpression(expression: IrContainerExpression, data: ReturnableBlockLoweringContext): IrExpression {
if (expression !is IrReturnableBlock) return super.visitContainerExpression(expression, data)
@@ -28,6 +28,6 @@ interface IrExpression : IrStatement, IrVarargElement {
}
interface IrExpressionWithCopy : IrExpression {
fun copy(): IrExpression
fun copy(): IrExpressionWithCopy
}