[JS IR BE] process empty loops correctly in BlockDecomposerLowering
This commit is contained in:
+11
-4
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContainerLoweringPass {
|
||||
|
||||
@@ -265,7 +266,7 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo
|
||||
}
|
||||
|
||||
newLoopBody.statements += JsIrBuilder.buildIfElse(unitType, breakCond, thenBlock)
|
||||
newLoopBody.statements += newBody!!
|
||||
newLoopBody.statements.addIfNotNull(newBody)
|
||||
|
||||
return loop.apply {
|
||||
condition = constTrue
|
||||
@@ -293,16 +294,22 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo
|
||||
// } while (cond)
|
||||
//
|
||||
override fun visitDoWhileLoop(loop: IrDoWhileLoop): IrExpression {
|
||||
val newBody = loop.body?.transform(statementTransformer, null)!!
|
||||
val newBody = loop.body?.transform(statementTransformer, null)
|
||||
val newCondition = loop.condition.transform(expressionTransformer, null)
|
||||
|
||||
if (newCondition is IrComposite) {
|
||||
val innerLoop = IrDoWhileLoopImpl(loop.startOffset, loop.endOffset, unitType, loop.origin, newBody, constFalse).apply {
|
||||
val innerLoop = IrDoWhileLoopImpl(loop.startOffset, loop.endOffset, unitType, loop.origin).apply {
|
||||
condition = constFalse
|
||||
body = newBody
|
||||
label = makeLoopLabel()
|
||||
}
|
||||
|
||||
val newLoopCondition = newCondition.statements.last() as IrExpression
|
||||
val newLoopBody = IrBlockImpl(newCondition.startOffset, newBody.endOffset, newBody.type).apply {
|
||||
val newLoopBody = IrBlockImpl(
|
||||
newCondition.startOffset,
|
||||
newBody?.endOffset ?: newCondition.endOffset,
|
||||
newBody?.type ?: unitType
|
||||
).apply {
|
||||
statements += innerLoop
|
||||
statements += newCondition.statements.run { subList(0, lastIndex) }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
fun box(): String {
|
||||
do while (false);
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
fun box(): String {
|
||||
while (false);
|
||||
|
||||
|
||||
+5
@@ -2149,6 +2149,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/expression/evaluationOrder/elvisWithBreakContinueReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyLoopWithBreakContinueReturnInCondition.kt")
|
||||
public void testEmptyLoopWithBreakContinueReturnInCondition() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/evaluationOrder/emptyLoopWithBreakContinueReturnInCondition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("equalsIntrinsicWithSideEffect.kt")
|
||||
public void testEqualsIntrinsicWithSideEffect() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/evaluationOrder/equalsIntrinsicWithSideEffect.kt");
|
||||
|
||||
+5
@@ -2149,6 +2149,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/expression/evaluationOrder/elvisWithBreakContinueReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("emptyLoopWithBreakContinueReturnInCondition.kt")
|
||||
public void testEmptyLoopWithBreakContinueReturnInCondition() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/evaluationOrder/emptyLoopWithBreakContinueReturnInCondition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("equalsIntrinsicWithSideEffect.kt")
|
||||
public void testEqualsIntrinsicWithSideEffect() throws Exception {
|
||||
runTest("js/js.translator/testData/box/expression/evaluationOrder/equalsIntrinsicWithSideEffect.kt");
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1236
|
||||
package foo
|
||||
|
||||
fun whileReturn(): String {
|
||||
var log = ""
|
||||
var i = 0
|
||||
while(if (i<2) { log += "A"; i++; true } else { return log + ":whileReturn:"});
|
||||
return ":whileReturn:after:"
|
||||
}
|
||||
|
||||
fun whileImmediateReturn(): String {
|
||||
while(return ":whileImmediateReturn:") {
|
||||
}
|
||||
return ":whileImmediateReturn:after"
|
||||
}
|
||||
|
||||
fun doWhileReturn(): String {
|
||||
var log = ""
|
||||
var i = 0
|
||||
do while(if (i<2) { log += "A"; i++; true} else { return log + ":doWhileReturn:"})
|
||||
return ":doWhileReturn:after:"
|
||||
}
|
||||
|
||||
fun doWhileReturnFromCondition(): String {
|
||||
do {
|
||||
} while(return ":doWhileReturnFromCondition:")
|
||||
return ":doWhileReturnFromCondition:after"
|
||||
}
|
||||
|
||||
fun forReturn(b: Boolean): String {
|
||||
for(i in (if (b) 1..2 else { return ":forReturn:"}));
|
||||
return ":forReturn:after:"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("AA:whileReturn:", whileReturn())
|
||||
|
||||
assertEquals(":whileImmediateReturn:", whileImmediateReturn())
|
||||
|
||||
assertEquals("AA:doWhileReturn:", doWhileReturn())
|
||||
|
||||
assertEquals(":doWhileReturnFromCondition:", doWhileReturnFromCondition())
|
||||
|
||||
assertEquals(":forReturn:after:", forReturn(true))
|
||||
|
||||
assertEquals(":forReturn:", forReturn(false))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user