[JS IR BE] Fix block decomposition lowering for dynamic expressions
This commit is contained in:
+33
-7
@@ -456,26 +456,30 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
|||||||
private fun mapArguments(
|
private fun mapArguments(
|
||||||
oldArguments: Collection<IrExpression?>,
|
oldArguments: Collection<IrExpression?>,
|
||||||
compositeCount: Int,
|
compositeCount: Int,
|
||||||
newStatements: MutableList<IrStatement>
|
newStatements: MutableList<IrStatement>,
|
||||||
|
dontDetachFirstArgument: Boolean = false
|
||||||
): List<IrExpression?> {
|
): List<IrExpression?> {
|
||||||
var compositesLeft = compositeCount
|
var compositesLeft = compositeCount
|
||||||
val arguments = mutableListOf<IrExpression?>()
|
val arguments = mutableListOf<IrExpression?>()
|
||||||
|
|
||||||
for (arg in oldArguments) {
|
for ((index, arg) in oldArguments.withIndex()) {
|
||||||
val value = if (arg is IrComposite) {
|
val value = if (arg is IrComposite) {
|
||||||
compositesLeft--
|
compositesLeft--
|
||||||
newStatements += arg.statements.run { subList(0, lastIndex) }
|
newStatements += arg.statements.run { subList(0, lastIndex) }
|
||||||
arg.statements.last() as IrExpression
|
arg.statements.last() as IrExpression
|
||||||
} else arg
|
} else arg
|
||||||
|
|
||||||
val newArg = if (compositesLeft != 0) {
|
val newArg = when {
|
||||||
if (value != null) {
|
compositesLeft == 0 -> value
|
||||||
|
index == 0 && dontDetachFirstArgument -> value
|
||||||
|
value == null -> value
|
||||||
|
else -> {
|
||||||
// TODO: do not wrap if value is pure (const, variable, etc)
|
// TODO: do not wrap if value is pure (const, variable, etc)
|
||||||
val irVar = makeTempVar(value.type, value)
|
val irVar = makeTempVar(value.type, value)
|
||||||
newStatements += irVar
|
newStatements += irVar
|
||||||
JsIrBuilder.buildGetValue(irVar.symbol)
|
JsIrBuilder.buildGetValue(irVar.symbol)
|
||||||
} else value
|
}
|
||||||
} else value
|
}
|
||||||
|
|
||||||
arguments += newArg
|
arguments += newArg
|
||||||
}
|
}
|
||||||
@@ -561,7 +565,12 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
|||||||
if (compositeCount == 0) return expression
|
if (compositeCount == 0) return expression
|
||||||
|
|
||||||
val newStatements = mutableListOf<IrStatement>()
|
val newStatements = mutableListOf<IrStatement>()
|
||||||
val newArguments = mapArguments(oldArguments, compositeCount, newStatements)
|
val newArguments = mapArguments(
|
||||||
|
oldArguments,
|
||||||
|
compositeCount,
|
||||||
|
newStatements,
|
||||||
|
dontDetachFirstArgument = expression.isReceiverNonDetachable()
|
||||||
|
)
|
||||||
|
|
||||||
expression.receiver = newArguments[0]
|
expression.receiver = newArguments[0]
|
||||||
?: error("No new receiver in destructured composite for:\n${expression.dump()}")
|
?: error("No new receiver in destructured composite for:\n${expression.dump()}")
|
||||||
@@ -576,6 +585,23 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
|||||||
return expression.run { IrCompositeImpl(startOffset, endOffset, type, null, newStatements) }
|
return expression.run { IrCompositeImpl(startOffset, endOffset, type, null, newStatements) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return if receiver expression cannot be detached from this expression
|
||||||
|
private fun IrDynamicOperatorExpression.isReceiverNonDetachable(): Boolean {
|
||||||
|
val receiver = when (val r = this.receiver) {
|
||||||
|
is IrComposite -> r.statements.lastOrNull() ?: return false
|
||||||
|
else -> r
|
||||||
|
}
|
||||||
|
|
||||||
|
val receiverIsMemberAccess =
|
||||||
|
receiver is IrDynamicMemberExpression ||
|
||||||
|
(receiver is IrDynamicOperatorExpression && receiver.operator == IrDynamicOperator.ARRAY_ACCESS)
|
||||||
|
|
||||||
|
val operatorDependsOnMemberAccess =
|
||||||
|
operator.isAssignmentOperator || operator == IrDynamicOperator.INVOKE
|
||||||
|
|
||||||
|
return receiverIsMemberAccess && operatorDependsOnMemberAccess
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
||||||
|
|
||||||
expression.run { if (statements.isEmpty()) return IrCompositeImpl(startOffset, endOffset, type, origin, listOf(unitValue)) }
|
expression.run { if (statements.isEmpty()) return IrCompositeImpl(startOffset, endOffset, type, origin, listOf(unitValue)) }
|
||||||
|
|||||||
Reference in New Issue
Block a user