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)
|
assert(symbol !in iteratorToLoopInfo)
|
||||||
|
|
||||||
val builder = context.createIrBuilder(scopeOwnerSymbol, variable.startOffset, variable.endOffset)
|
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
|
val progressionInfo = initializer.dispatchReceiver?.accept(ProgressionInfoBuilder(), null) ?: return null
|
||||||
return builder.irBlock {
|
|
||||||
|
with(builder) {
|
||||||
with(progressionInfo) {
|
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 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.
|
// Don't call progression bound calculation if the step is 1.
|
||||||
val boundExpression = if (needBoundCalculation) {
|
val boundExpression = if (needBoundCalculation) {
|
||||||
irGetProgressionBound(progressionType, inductionVariable.symbol, last, stepValue.symbol)
|
irGetProgressionBound(progressionType, inductionVariable.symbol, last, stepValue.symbol)
|
||||||
} else {
|
} else {
|
||||||
last.castIfNecessary(progressionType)
|
last.castIfNecessary(progressionType)
|
||||||
}
|
}
|
||||||
val boundValue = irTemporary(boundExpression, "bound")
|
val boundValue = scope.createTemporaryVariable(boundExpression, "bound")
|
||||||
|
statements.add(boundValue)
|
||||||
|
|
||||||
iteratorToLoopInfo[symbol] = ForLoopInfo(progressionInfo,
|
iteratorToLoopInfo[symbol] = ForLoopInfo(progressionInfo,
|
||||||
inductionVariable.symbol,
|
inductionVariable.symbol,
|
||||||
boundValue.symbol,
|
boundValue.symbol,
|
||||||
stepValue.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)) {
|
with(context.createIrBuilder(scopeOwnerSymbol)) {
|
||||||
// Transform accesses to the old iterator (see visitVariable method). Store loopVariable in loopInfo.
|
// 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 (newCondition, forLoopInfo) = buildNewCondition(loop.condition) ?: return super.visitWhileLoop(loop)
|
||||||
|
|
||||||
val newLoop = IrDoWhileLoopImpl(loop.startOffset, loop.endOffset, loop.type, loop.origin).apply {
|
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"
|
"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) {
|
task local_variable(type: RunKonanTest) {
|
||||||
source = "codegen/basics/local_variable.kt"
|
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