backend: Use IrComposite instead of IrBlock in headers of 'for' loops
This commit is contained in:
+27
-6
@@ -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<IrStatement>()
|
||||
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val sq = buildSequence {
|
||||
for (i in 0..6 step 2) {
|
||||
print("before: $i ")
|
||||
yield(i)
|
||||
println("after: $i")
|
||||
}
|
||||
}
|
||||
println("Got: ${sq.joinToString(separator = " ")}")
|
||||
}
|
||||
Reference in New Issue
Block a user