[JS IR] Keep box and unbox intrinsics in call args after decomposing
^KT-59717 Fixed
This commit is contained in:
committed by
Space Team
parent
148d8c9246
commit
4695dca056
@@ -97,7 +97,9 @@ class JsIrBackendContext(
|
||||
override fun isSideEffectFree(call: IrCall): Boolean =
|
||||
call.symbol in intrinsics.primitiveToLiteralConstructor.values ||
|
||||
call.symbol == intrinsics.arrayLiteral ||
|
||||
call.symbol == intrinsics.arrayConcat
|
||||
call.symbol == intrinsics.arrayConcat ||
|
||||
call.symbol == intrinsics.jsBoxIntrinsic ||
|
||||
call.symbol == intrinsics.jsUnboxIntrinsic
|
||||
|
||||
val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false
|
||||
val errorPolicy = configuration[JSConfigurationKeys.ERROR_TOLERANCE_POLICY] ?: ErrorTolerancePolicy.DEFAULT
|
||||
|
||||
+44
-4
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.typeArguments
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
@@ -94,7 +95,7 @@ abstract class AbstractBlockDecomposerLowering(private val context: JsCommonBack
|
||||
}
|
||||
|
||||
class BlockDecomposerTransformer(
|
||||
private val context: CommonBackendContext,
|
||||
private val context: JsCommonBackendContext,
|
||||
private val unreachableExpression: () -> IrExpression
|
||||
) : IrElementTransformerVoid() {
|
||||
private lateinit var function: IrDeclarationParent
|
||||
@@ -111,6 +112,9 @@ class BlockDecomposerTransformer(
|
||||
|
||||
private val booleanNotSymbol = context.irBuiltIns.booleanNotSymbol
|
||||
|
||||
private val boxIntrinsic = context.inlineClassesUtils.boxIntrinsic
|
||||
private val unboxIntrinsic = context.inlineClassesUtils.unboxIntrinsic
|
||||
|
||||
override fun visitScript(declaration: IrScript): IrStatement {
|
||||
function = declaration
|
||||
|
||||
@@ -537,9 +541,9 @@ class BlockDecomposerTransformer(
|
||||
value.isPure(anyVariable = false, context = context) -> value
|
||||
else -> {
|
||||
// TODO: do not wrap if value is pure (const, variable, etc)
|
||||
val irVar = makeTempVar(value.type, value)
|
||||
newStatements += irVar
|
||||
JsIrBuilder.buildGetValue(irVar.symbol)
|
||||
val (newArg, tempVar) = mapArgument(value)
|
||||
newStatements += tempVar
|
||||
newArg
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,6 +552,42 @@ class BlockDecomposerTransformer(
|
||||
return arguments
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the passing argument and store it in a temporary variable.
|
||||
* However, the box and unbox intrinsics should be preserved in the call.
|
||||
* They can be used later for optimizations, for example, in [EqualityAndComparisonCallsTransformer].
|
||||
* Example:
|
||||
* foo(boxIntrinsic(<expr>))
|
||||
* should be transformed to:
|
||||
* var tmp = <expr>
|
||||
* foo(boxIntrinsic(tmp))
|
||||
*/
|
||||
private fun mapArgument(arg: IrExpression): Pair<IrExpression, IrVariable> {
|
||||
var saveToTmp = arg
|
||||
var rootIntrinsicCall: IrCall? = null
|
||||
var lastIntrinsicCall: IrCall? = null
|
||||
while (saveToTmp is IrCall && (saveToTmp.symbol == boxIntrinsic || saveToTmp.symbol == unboxIntrinsic)) {
|
||||
if (lastIntrinsicCall == null) {
|
||||
lastIntrinsicCall = JsIrBuilder.buildCall(saveToTmp.symbol, saveToTmp.type, saveToTmp.typeArguments.filterNotNull())
|
||||
rootIntrinsicCall = lastIntrinsicCall
|
||||
} else {
|
||||
val nextCall = JsIrBuilder.buildCall(saveToTmp.symbol)
|
||||
lastIntrinsicCall.putValueArgument(0, nextCall)
|
||||
lastIntrinsicCall = nextCall
|
||||
}
|
||||
saveToTmp = saveToTmp.getValueArgument(0) ?: error("expect passing 1 argument to boxing intrinsic")
|
||||
}
|
||||
|
||||
val irTempVar = makeTempVar(saveToTmp.type, saveToTmp)
|
||||
val irGetTempVar = JsIrBuilder.buildGetValue(irTempVar.symbol)
|
||||
val newArg = lastIntrinsicCall?.let {
|
||||
it.putValueArgument(0, irGetTempVar)
|
||||
rootIntrinsicCall
|
||||
} ?: irGetTempVar
|
||||
|
||||
return newArg to irTempVar
|
||||
}
|
||||
|
||||
// TODO: remove this when vararg is lowered
|
||||
override fun visitVararg(expression: IrVararg): IrExpression {
|
||||
expression.transformChildrenVoid(expressionTransformer)
|
||||
|
||||
Reference in New Issue
Block a user