backend: Use IrComposite instead of IrBlock in headers of 'for' loops

This commit is contained in:
Ilya Matveev
2017-07-19 18:16:38 +07:00
committed by ilmat192
parent c4acdf1b25
commit 0ddc002b8d
3 changed files with 48 additions and 6 deletions
@@ -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 {
+9
View File
@@ -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 = " ")}")
}