diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt index 322257e5752..7436dd11d3d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/ForLoopsLowering.kt @@ -300,24 +300,38 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo assert(symbol !in iteratorToLoopInfo) val builder = context.createIrBuilder(scopeOwnerSymbol, variable.startOffset, variable.endOffset) - // Collect loop info and form the loop header block. + // Collect loop info and form the loop header composite. val progressionInfo = initializer.dispatchReceiver?.accept(ProgressionInfoBuilder(), null) ?: return null - return builder.irBlock { + + with(builder) { with(progressionInfo) { - val inductionVariable = irTemporaryVar(first.castIfNecessary(progressionType), "inductionVariable") + val statements = mutableListOf() + + + val inductionVariable = scope.createTemporaryVariable(first.castIfNecessary(progressionType), + "inductionVariable", + true) + statements.add(inductionVariable) + val stepExpression = (if (increasing) step else step?.unaryMinus()) ?: defaultStep(startOffset, endOffset) - val stepValue = irTemporary(stepExpression, "step") + val stepValue = scope.createTemporaryVariable(stepExpression, "step") + statements.add(stepValue) + // Don't call progression bound calculation if the step is 1. val boundExpression = if (needBoundCalculation) { irGetProgressionBound(progressionType, inductionVariable.symbol, last, stepValue.symbol) } else { last.castIfNecessary(progressionType) } - val boundValue = irTemporary(boundExpression, "bound") + val boundValue = scope.createTemporaryVariable(boundExpression, "bound") + statements.add(boundValue) + iteratorToLoopInfo[symbol] = ForLoopInfo(progressionInfo, inductionVariable.symbol, boundValue.symbol, stepValue.symbol) + + return IrCompositeImpl(startOffset, endOffset, context.builtIns.unitType, null, statements) } } } @@ -411,7 +425,14 @@ private class ForLoopsTransformer(val context: Context) : IrElementTransformerVo with(context.createIrBuilder(scopeOwnerSymbol)) { // Transform accesses to the old iterator (see visitVariable method). Store loopVariable in loopInfo. - val newBody = loop.body?.transform(this@ForLoopsTransformer, null) + // Replace not transparent containers with transparent ones (IrComposite) + val newBody = loop.body?.transform(this@ForLoopsTransformer, null)?.let { + if (it is IrContainerExpression && !it.isTransparentScope) { + with(it) { IrCompositeImpl(startOffset, endOffset, type, origin, statements) } + } else { + it + } + } val (newCondition, forLoopInfo) = buildNewCondition(loop.condition) ?: return super.visitWhileLoop(loop) val newLoop = IrDoWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, loop.origin).apply { diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 635bff2eae8..94d0e738fa0 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -348,6 +348,15 @@ task codegen_controlflow_for_loops_nested(type: RunKonanTest) { "00 10 20 \n" } +task codegen_controlflow_for_loops_coroutines(type: RunKonanTest) { + source = "codegen/controlflow/for_loops_coroutines.kt" + goldValue = "before: 0 after: 0\n" + + "before: 2 after: 2\n" + + "before: 4 after: 4\n" + + "before: 6 after: 6\n" + + "Got: 0 2 4 6\n" +} + task local_variable(type: RunKonanTest) { source = "codegen/basics/local_variable.kt" } diff --git a/backend.native/tests/codegen/controlflow/for_loops_coroutines.kt b/backend.native/tests/codegen/controlflow/for_loops_coroutines.kt new file mode 100644 index 00000000000..140f069bec8 --- /dev/null +++ b/backend.native/tests/codegen/controlflow/for_loops_coroutines.kt @@ -0,0 +1,12 @@ +import kotlin.coroutines.experimental.* + +fun main(args: Array) { + val sq = buildSequence { + for (i in 0..6 step 2) { + print("before: $i ") + yield(i) + println("after: $i") + } + } + println("Got: ${sq.joinToString(separator = " ")}") +} \ No newline at end of file