Make all progression headers inclusive, and decrement last for

last-exclusive progressions (i.e., "until" progressions and loop over
array indices).

This change makes it possible to correctly implement the handling of
"step" progressions. Computing the last element of a stepped progression
requires that the last is inclusive.

Also invert the while loop (into if + do-while) that is used when
lowering for-loops over progressions that cannot overflow. This keeps
the performance characteristics closer to the ForLoopsLowering in
kotlin-native, since the goal is to converge to this shared version.

Also used IrType instead of KotlinType, where possible.

 https://github.com/JetBrains/kotlin/pull/2390
 https://github.com/JetBrains/kotlin/pull/2305
This commit is contained in:
Mark Punzalan
2019-06-14 00:59:47 -07:00
committed by Mikhael Bogdanov
parent 39f6416757
commit de1e27c584
75 changed files with 1873 additions and 377 deletions
@@ -44,22 +44,24 @@ val forLoopsPhase = makeIrFilePhase(
* } * }
* ``` * ```
* We transform it into one of the following loops: * We transform it into one of the following loops:
*
* ``` * ```
* // 1. If the induction variable cannot overflow, i.e., `B` is const and != MAX_VALUE (if increasing, or MIN_VALUE if decreasing). * // 1. If the induction variable cannot overflow, i.e., `B` is const and != MAX_VALUE (if increasing, or MIN_VALUE if decreasing).
* *
* var inductionVar = A * var inductionVar = A
* var last = B * val last = B
* while (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing) * if (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing)
* val loopVar = inductionVar * // Loop is not empty
* inductionVar++ // (`inductionVar--` if the progression is decreasing) * do {
* // Loop body * val loopVar = inductionVar
* inductionVar++ // (`inductionVar--` if the progression is decreasing)
* // Loop body
* } while (inductionVar <= last)
* } * }
* *
* // 2. If the induction variable CAN overflow, i.e., `last` is not const or is MAX/MIN_VALUE: * // 2. If the induction variable CAN overflow, i.e., `last` is not const or is MAX/MIN_VALUE:
* *
* var inductionVar = A * var inductionVar = A
* var last = B * val last = B
* if (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing) * if (inductionVar <= last) { // (`inductionVar >= last` if the progression is decreasing)
* // Loop is not empty * // Loop is not empty
* do { * do {
@@ -68,15 +70,18 @@ val forLoopsPhase = makeIrFilePhase(
* // Loop body * // Loop body
* } while (loopVar != last) * } while (loopVar != last)
* } * }
* * ```
* // 3. If loop is an until loop (e.g., `for (i in A until B)`), it cannot overflow and we use `<` for comparisons: * If loop is an until loop (e.g., `for (i in A until B)`), it is transformed into:
* * ```
* var inductionVar = A * var inductionVar = A
* var last = B * val last = B - 1
* while (inductionVar < last) { * if (inductionVar <= last && B != MIN_VALUE) {
* val loopVar = inductionVar * // Loop is not empty
* inductionVar++ * do {
* // Loop body * val loopVar = inductionVar
* inductionVar++
* // Loop body
* } while (inductionVar <= last)
* } * }
* ``` * ```
* In case of iteration over an array (e.g., `for (i in array)`), we transform it into the following: * In case of iteration over an array (e.g., `for (i in array)`), we transform it into the following:
@@ -221,7 +226,7 @@ private class RangeLoopTransformer(
// inductionVariable = inductionVariable + step // inductionVariable = inductionVariable + step
return with(context.createIrBuilder(getScopeOwnerSymbol(), initializer.startOffset, initializer.endOffset)) { return with(context.createIrBuilder(getScopeOwnerSymbol(), initializer.startOffset, initializer.endOffset)) {
variable.initializer = forLoopInfo.initializeLoopVariable(symbols, this) variable.initializer = forLoopInfo.initializeLoopVariable(symbols, this)
val increment = forLoopInfo.buildIncrementInductionVariableExpression(this) val increment = forLoopInfo.incrementInductionVariable(this)
IrCompositeImpl( IrCompositeImpl(
variable.startOffset, variable.startOffset,
variable.endOffset, variable.endOffset,
@@ -12,16 +12,10 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
@@ -31,7 +25,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
// TODO: Handle UIntProgression, ULongProgression // TODO: Handle UIntProgression, ULongProgression
/** Represents a progression type in the Kotlin stdlib. */ /** Represents a progression type in the Kotlin stdlib. */
enum class ProgressionType(val elementCastFunctionName: Name, val stepCastFunctionName: Name) { internal enum class ProgressionType(val elementCastFunctionName: Name, val stepCastFunctionName: Name) {
INT_PROGRESSION(Name.identifier("toInt"), Name.identifier("toInt")), INT_PROGRESSION(Name.identifier("toInt"), Name.identifier("toInt")),
LONG_PROGRESSION(Name.identifier("toLong"), Name.identifier("toLong")), LONG_PROGRESSION(Name.identifier("toLong"), Name.identifier("toLong")),
CHAR_PROGRESSION(Name.identifier("toChar"), Name.identifier("toInt")); CHAR_PROGRESSION(Name.identifier("toChar"), Name.identifier("toInt"));
@@ -59,7 +53,19 @@ enum class ProgressionType(val elementCastFunctionName: Name, val stepCastFuncti
} }
} }
internal enum class ProgressionDirection { DECREASING, INCREASING, UNKNOWN } internal enum class ProgressionDirection {
DECREASING {
override fun asReversed() = INCREASING
},
INCREASING {
override fun asReversed() = DECREASING
},
UNKNOWN {
override fun asReversed() = UNKNOWN
};
abstract fun asReversed(): ProgressionDirection
}
/** Information about a loop that is required by [HeaderProcessor] to build a [ForLoopHeader]. */ /** Information about a loop that is required by [HeaderProcessor] to build a [ForLoopHeader]. */
internal sealed class HeaderInfo( internal sealed class HeaderInfo(
@@ -67,25 +73,13 @@ internal sealed class HeaderInfo(
val first: IrExpression, val first: IrExpression,
val last: IrExpression, val last: IrExpression,
val step: IrExpression, val step: IrExpression,
val isFirstInclusive: Boolean, val isReversed: Boolean,
val isLastInclusive: Boolean, val direction: ProgressionDirection,
val isReversed: Boolean val additionalNotEmptyCondition: IrExpression?
) { ) {
val direction: ProgressionDirection by lazy {
// If step is a constant (either Int or Long), then we can determine the direction.
val stepValue = (step as? IrConst<*>)?.value as? Number
val stepValueAsLong = stepValue?.toLong()
when {
stepValueAsLong == null -> ProgressionDirection.UNKNOWN
stepValueAsLong < 0L -> ProgressionDirection.DECREASING
stepValueAsLong > 0L -> ProgressionDirection.INCREASING
else -> ProgressionDirection.UNKNOWN
}
}
/** /**
* Returns a copy of this [HeaderInfo] with the values reversed. * Returns a copy of this [HeaderInfo] with the values reversed.
* I.e., first and last (and their inclusiveness) are swapped, step is negated. * I.e., first and last are swapped, step is negated.
* Returns null if the iterable cannot be iterated in reverse. * Returns null if the iterable cannot be iterated in reverse.
*/ */
abstract fun asReversed(): HeaderInfo? abstract fun asReversed(): HeaderInfo?
@@ -97,23 +91,18 @@ internal class ProgressionHeaderInfo(
first: IrExpression, first: IrExpression,
last: IrExpression, last: IrExpression,
step: IrExpression, step: IrExpression,
isFirstInclusive: Boolean = true,
isLastInclusive: Boolean = true,
isReversed: Boolean = false, isReversed: Boolean = false,
canOverflow: Boolean? = null,
direction: ProgressionDirection,
additionalNotEmptyCondition: IrExpression? = null,
val additionalVariables: List<IrVariable> = listOf() val additionalVariables: List<IrVariable> = listOf()
) : HeaderInfo(progressionType, first, last, step, isFirstInclusive, isLastInclusive, isReversed) { ) : HeaderInfo(progressionType, first, last, step, isReversed, direction, additionalNotEmptyCondition) {
val canOverflow: Boolean by lazy { val canOverflow: Boolean by lazy {
// Last-exclusive progressions can never overflow. if (canOverflow != null) return@lazy canOverflow
if (!isLastInclusive) return@lazy false
// Induction variable can overflow if it is not a const, or is MAX/MIN_VALUE (depending on direction). // Induction variable can overflow if it is not a const, or is MAX/MIN_VALUE (depending on direction).
val lastValue = (last as? IrConst<*>)?.value val lastValueAsLong = last.constLongValue ?: return@lazy true // If "last" is not a const Number or Char.
val lastValueAsLong = when (lastValue) {
is Number -> lastValue.toLong()
is Char -> lastValue.toLong()
else -> return@lazy true // If "last" is not a const Number or Char.
}
val constLimitAsLong = when (direction) { val constLimitAsLong = when (direction) {
ProgressionDirection.UNKNOWN -> ProgressionDirection.UNKNOWN ->
// If we don't know the direction, we can't be sure which limit to use. // If we don't know the direction, we can't be sure which limit to use.
@@ -139,9 +128,9 @@ internal class ProgressionHeaderInfo(
first = last, first = last,
last = first, last = first,
step = step.negate(), step = step.negate(),
isFirstInclusive = isLastInclusive,
isLastInclusive = isFirstInclusive,
isReversed = !isReversed, isReversed = !isReversed,
direction = direction.asReversed(),
additionalNotEmptyCondition = additionalNotEmptyCondition,
additionalVariables = additionalVariables additionalVariables = additionalVariables
) )
} }
@@ -157,9 +146,9 @@ internal class ArrayHeaderInfo(
first, first,
last, last,
step, step,
isFirstInclusive = true, isReversed = false,
isLastInclusive = false, direction = ProgressionDirection.INCREASING,
isReversed = false additionalNotEmptyCondition = null
) { ) {
// Technically one can easily iterate over an array in reverse by swapping first/last and // Technically one can easily iterate over an array in reverse by swapping first/last and
// negating the step. However, Array.reversed() and Array.reversedArray() return a collection // negating the step. However, Array.reversed() and Array.reversedArray() return a collection
@@ -177,21 +166,6 @@ internal class ArrayHeaderInfo(
override fun asReversed(): HeaderInfo? = null override fun asReversed(): HeaderInfo? = null
} }
/** Return the negated value if the expression is const, otherwise call unaryMinus(). */
private fun IrExpression.negate(): IrExpression {
val stepValue = (this as? IrConst<*>)?.value as? Number
return when (stepValue) {
is Int -> IrConstImpl(startOffset, endOffset, type, IrConstKind.Int, -stepValue)
is Long -> IrConstImpl(startOffset, endOffset, type, IrConstKind.Long, -stepValue)
else -> {
val unaryMinusFun = type.getClass()!!.functions.first { it.name.asString() == "unaryMinus" }
IrCallImpl(startOffset, endOffset, type, unaryMinusFun.symbol, unaryMinusFun.descriptor).apply {
dispatchReceiver = this@negate
}
}
}
}
/** Matches an iterable expression and builds a [HeaderInfo] from the expression. */ /** Matches an iterable expression and builds a [HeaderInfo] from the expression. */
internal interface HeaderInfoHandler<E : IrExpression, D> { internal interface HeaderInfoHandler<E : IrExpression, D> {
/** Returns true if the handler can build a [HeaderInfo] from the expression. */ /** Returns true if the handler can build a [HeaderInfo] from the expression. */
@@ -227,7 +201,13 @@ internal class HeaderInfoBuilder(context: CommonBackendContext, private val scop
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
// TODO: Include unsigned types // TODO: Include unsigned types
private val progressionElementTypes = symbols.integerClassesTypes + context.irBuiltIns.char private val progressionElementTypes = listOf(
context.irBuiltIns.byteType,
context.irBuiltIns.shortType,
context.irBuiltIns.intType,
context.irBuiltIns.longType,
context.irBuiltIns.charType
)
private val progressionHandlers = listOf( private val progressionHandlers = listOf(
IndicesHandler(context), IndicesHandler(context),
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irComposite
import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
@@ -18,13 +17,11 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.name.Name
/** /**
* Contains the loop and expression to replace the old loop. * Contains the loop and expression to replace the old loop.
@@ -44,7 +41,8 @@ internal sealed class ForLoopHeader(
val inductionVariable: IrVariable, val inductionVariable: IrVariable,
val last: IrVariable, val last: IrVariable,
val step: IrVariable, val step: IrVariable,
var loopVariable: IrVariable? = null var loopVariable: IrVariable? = null,
val isLastInclusive: Boolean
) { ) {
/** Expression used to initialize the loop variable at the beginning of the loop. */ /** Expression used to initialize the loop variable at the beginning of the loop. */
abstract fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder): IrExpression abstract fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder): IrExpression
@@ -55,17 +53,34 @@ internal sealed class ForLoopHeader(
/** Builds a new loop from the old loop. */ /** Builds a new loop from the old loop. */
abstract fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?): LoopReplacement abstract fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?): LoopReplacement
/** Statement used to increment the induction variable. */
fun incrementInductionVariable(builder: DeclarationIrBuilder): IrStatement = with(builder) {
// inductionVariable = inductionVariable + step
val plusFun = inductionVariable.type.getClass()!!.functions.first {
it.name.asString() == "plus" &&
it.valueParameters.size == 1 &&
it.valueParameters[0].type == step.type
}
irSetVar(
inductionVariable.symbol, irCallOp(
plusFun.symbol, plusFun.returnType,
irGet(inductionVariable),
irGet(step)
)
)
}
protected fun buildLoopCondition(builder: DeclarationIrBuilder): IrExpression = protected fun buildLoopCondition(builder: DeclarationIrBuilder): IrExpression =
with(builder) { with(builder) {
val builtIns = context.irBuiltIns val builtIns = context.irBuiltIns
val progressionType = headerInfo.progressionType val progressionType = headerInfo.progressionType
val progressionKotlinType = progressionType.elementType(builtIns).toKotlinType() val progressionKotlinType = progressionType.elementType(builtIns).toKotlinType()
val compFun = val compFun =
if (headerInfo.isLastInclusive) builtIns.lessOrEqualFunByOperandType[progressionKotlinType]!! if (isLastInclusive) builtIns.lessOrEqualFunByOperandType[progressionKotlinType]!!
else builtIns.lessFunByOperandType[progressionKotlinType]!! else builtIns.lessFunByOperandType[progressionKotlinType]!!
// The default condition depends on the direction. // The default condition depends on the direction.
return when (headerInfo.direction) { when (headerInfo.direction) {
ProgressionDirection.DECREASING -> ProgressionDirection.DECREASING ->
// last <= inductionVar (use `<` if last is exclusive) // last <= inductionVar (use `<` if last is exclusive)
irCall(compFun).apply { irCall(compFun).apply {
@@ -114,7 +129,7 @@ internal class ProgressionLoopHeader(
inductionVariable: IrVariable, inductionVariable: IrVariable,
last: IrVariable, last: IrVariable,
step: IrVariable step: IrVariable
) : ForLoopHeader(headerInfo, inductionVariable, last, step) { ) : ForLoopHeader(headerInfo, inductionVariable, last, step, isLastInclusive = true) {
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) { override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
// loopVariable = inductionVariable // loopVariable = inductionVariable
@@ -135,9 +150,9 @@ internal class ProgressionLoopHeader(
(if (headerInfo.isReversed) listOf(last, inductionVariable) else listOf(inductionVariable, last)) + (if (headerInfo.isReversed) listOf(last, inductionVariable) else listOf(inductionVariable, last)) +
step step
override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?): LoopReplacement { override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?) =
with(builder) { with(builder) {
var (newLoop, replacementExpression) = if (headerInfo.canOverflow) { val newLoop = if (headerInfo.canOverflow) {
// If the induction variable CAN overflow, we cannot use it in the loop condition. Loop is lowered into something like: // If the induction variable CAN overflow, we cannot use it in the loop condition. Loop is lowered into something like:
// //
// if (inductionVar <= last) { // if (inductionVar <= last) {
@@ -148,46 +163,37 @@ internal class ProgressionLoopHeader(
// // Loop body // // Loop body
// } while (loopVar != last) // } while (loopVar != last)
// } // }
assert(loopVariable != null) IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
val booleanNotFun = context.irBuiltIns.booleanClass.functions.first { it.owner.name.asString() == "not" }
val newCondition = irCallOp(booleanNotFun, booleanNotFun.owner.returnType, irCall(context.irBuiltIns.eqeqSymbol).apply {
putValueArgument(0, irGet(loopVariable!!))
putValueArgument(1, irGet(last))
})
val newLoop = IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
label = oldLoop.label label = oldLoop.label
condition = newCondition condition = irNotEquals(irGet(loopVariable!!), irGet(last))
body = newBody body = newBody
} }
val notEmptyCheck = irIfThen(buildLoopCondition(builder), newLoop)
LoopReplacement(newLoop, notEmptyCheck)
} else { } else {
// If the induction variable can NOT overflow, use a simple while loop. Loop is lowered into something like: // If the induction variable can NOT overflow, use a do-while loop. Loop is lowered into something like:
// //
// while (inductionVar <= last) { // if (inductionVar <= last) {
// val loopVar = inductionVar // do {
// inductionVar += step // val loopVar = inductionVar
// // Loop body // inductionVar += step
// // Loop body
// } while (inductionVar <= last)
// } // }
val newLoop = IrWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { //
// Even though this can be simplified into a simpler while loop, using if + do-while (i.e., doing a loop inversion)
// performs better in benchmarks. In cases where `last` is a constant, the `if` may be optimized away.
IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
label = oldLoop.label label = oldLoop.label
condition = buildLoopCondition(this@with) condition = buildLoopCondition(this@with)
body = newBody body = newBody
} }
LoopReplacement(newLoop, newLoop)
} }
if (!headerInfo.isFirstInclusive) { val loopCondition = buildLoopCondition(this@with)
// Pre-increment the induction variable. // Combine with the additional "not empty" condition, if any.
replacementExpression = irComposite(replacementExpression) { val notEmptyCheck =
+buildIncrementInductionVariableExpression(this@with) irIfThen(headerInfo.additionalNotEmptyCondition?.let { context.andand(it, loopCondition) } ?: loopCondition, newLoop)
+replacementExpression LoopReplacement(newLoop, notEmptyCheck)
}
}
return LoopReplacement(newLoop, replacementExpression)
} }
}
} }
internal class ArrayLoopHeader( internal class ArrayLoopHeader(
@@ -195,7 +201,7 @@ internal class ArrayLoopHeader(
inductionVariable: IrVariable, inductionVariable: IrVariable,
last: IrVariable, last: IrVariable,
step: IrVariable step: IrVariable
) : ForLoopHeader(headerInfo, inductionVariable, last, step) { ) : ForLoopHeader(headerInfo, inductionVariable, last, step, isLastInclusive = false) {
override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) { override fun initializeLoopVariable(symbols: Symbols<CommonBackendContext>, builder: DeclarationIrBuilder) = with(builder) {
// inductionVar = loopVar[inductionVariable] // inductionVar = loopVar[inductionVariable]
@@ -224,14 +230,7 @@ internal class ArrayLoopHeader(
condition = buildLoopCondition(this@with) condition = buildLoopCondition(this@with)
body = newBody body = newBody
} }
val replacementExpression = if (!headerInfo.isFirstInclusive) { LoopReplacement(newLoop, newLoop)
// Pre-increment the induction variable.
irComposite(newLoop) {
+buildIncrementInductionVariableExpression(this@with)
+newLoop
}
} else newLoop
LoopReplacement(newLoop, replacementExpression)
} }
} }
@@ -340,30 +339,4 @@ internal class HeaderProcessor(
} else { } else {
expression expression
} }
private fun IrExpression.castIfNecessary(targetType: IrType, numberCastFunctionName: Name): IrExpression {
return if (type.toKotlinType() == targetType.toKotlinType()) {
this
} else {
val function = type.getClass()!!.functions.first { it.name == numberCastFunctionName }
IrCallImpl(startOffset, endOffset, function.returnType, function.symbol)
.apply { dispatchReceiver = this@castIfNecessary }
}
}
} }
internal fun ForLoopHeader.buildIncrementInductionVariableExpression(builder: DeclarationIrBuilder): IrExpression = with(builder) {
// inductionVariable = inductionVariable + step
val plusFun = inductionVariable.type.getClass()!!.functions.first {
it.name.asString() == "plus" &&
it.valueParameters.size == 1 &&
it.valueParameters[0].type.toKotlinType() == step.type.toKotlinType()
}
irSetVar(
inductionVariable.symbol, irCallOp(
plusFun.symbol, plusFun.returnType,
irGet(inductionVariable),
irGet(step)
)
)
}
@@ -11,31 +11,31 @@ import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher
import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irInt
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
import org.jetbrains.kotlin.ir.util.properties import org.jetbrains.kotlin.ir.util.properties
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.SimpleType
/** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */ /** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */
internal class RangeToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<SimpleType>) : internal class RangeToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<IrType>) :
ProgressionHandler { ProgressionHandler {
override val matcher = SimpleCalleeMatcher { override val matcher = SimpleCalleeMatcher {
dispatchReceiver { it != null && it.type.toKotlinType() in progressionElementTypes } dispatchReceiver { it != null && it.type in progressionElementTypes }
fqName { it.pathSegments().last() == Name.identifier("rangeTo") } fqName { it.pathSegments().last() == Name.identifier("rangeTo") }
parameterCount { it == 1 } parameterCount { it == 1 }
parameter(0) { it.type.toKotlinType() in progressionElementTypes } parameter(0) { it.type in progressionElementTypes }
} }
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) =
@@ -44,19 +44,20 @@ internal class RangeToHandler(private val context: CommonBackendContext, private
data, data,
first = expression.dispatchReceiver!!, first = expression.dispatchReceiver!!,
last = expression.getValueArgument(0)!!, last = expression.getValueArgument(0)!!,
step = irInt(1) step = irInt(1),
direction = ProgressionDirection.INCREASING
) )
} }
} }
/** Builds a [HeaderInfo] for progressions built using the `downTo` extension function. */ /** Builds a [HeaderInfo] for progressions built using the `downTo` extension function. */
internal class DownToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<SimpleType>) : internal class DownToHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<IrType>) :
ProgressionHandler { ProgressionHandler {
override val matcher = SimpleCalleeMatcher { override val matcher = SimpleCalleeMatcher {
singleArgumentExtension(FqName("kotlin.ranges.downTo"), progressionElementTypes) singleArgumentExtension(FqName("kotlin.ranges.downTo"), progressionElementTypes)
parameterCount { it == 1 } parameterCount { it == 1 }
parameter(0) { it.type.toKotlinType() in progressionElementTypes } parameter(0) { it.type in progressionElementTypes }
} }
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
@@ -65,64 +66,193 @@ internal class DownToHandler(private val context: CommonBackendContext, private
data, data,
first = expression.extensionReceiver!!, first = expression.extensionReceiver!!,
last = expression.getValueArgument(0)!!, last = expression.getValueArgument(0)!!,
step = irInt(-1) step = irInt(-1),
direction = ProgressionDirection.DECREASING
) )
} }
} }
/** Builds a [HeaderInfo] for progressions built using the `until` extension function. */ /** Builds a [HeaderInfo] for progressions built using the `until` extension function. */
internal class UntilHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<SimpleType>) : internal class UntilHandler(private val context: CommonBackendContext, private val progressionElementTypes: Collection<IrType>) :
ProgressionHandler { ProgressionHandler {
override val matcher = SimpleCalleeMatcher { override val matcher = SimpleCalleeMatcher {
singleArgumentExtension(FqName("kotlin.ranges.until"), progressionElementTypes) singleArgumentExtension(FqName("kotlin.ranges.until"), progressionElementTypes)
parameterCount { it == 1 } parameterCount { it == 1 }
parameter(0) { it.type.toKotlinType() in progressionElementTypes } parameter(0) { it.type in progressionElementTypes }
} }
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// `A until B` is essentially the same as `A .. (B-1)`. However, B could be MIN_VALUE and hence `(B-1)` could underflow.
// If B is MIN_VALUE, then `A until B` is an empty range. We handle this special case be adding an additional "not empty"
// condition in the lowered for-loop. Therefore the following for-loop:
//
// for (i in A until B) { // Loop body }
//
// is lowered into:
//
// var inductionVar = A
// val last = B - 1
// if (inductionVar <= last && B != MIN_VALUE) {
// // Loop is not empty
// do {
// val loopVar = inductionVar
// inductionVar++
// // Loop body
// } while (inductionVar <= last)
// }
//
// However, `B` may be an expression with side-effects that should only be evaluated once, and `A` may also have side-effects.
// They are evaluated once and in the correct order (`A` then `B`), the final lowered form is:
//
// // Additional variables
// val untilReceiverValue = A
// val untilArg = B
// // Standard form of loop over progression
// var inductionVar = untilReceiverValue
// val last = untilArg - 1
// if (inductionVar <= last && untilFunArg != MIN_VALUE) {
// // Loop is not empty
// do {
// val loopVar = inductionVar
// inductionVar++
// // Loop body
// } while (inductionVar <= last)
// }
val receiverValue = expression.extensionReceiver!!
val untilArg = expression.getValueArgument(0)!!
// Ensure that the argument conforms to the progression type before we decrement.
val untilArgCasted = untilArg.castIfNecessary(
data.elementType(context.irBuiltIns),
data.elementCastFunctionName
)
// To reduce local variable usage, we create and use temporary variables only if necessary.
var receiverValueVar: IrVariable? = null
var untilArgVar: IrVariable? = null
var additionalVariables = emptyList<IrVariable>()
if (untilArg.canHaveSideEffects) {
if (receiverValue.canHaveSideEffects) {
receiverValueVar = scope.createTemporaryVariable(receiverValue, nameHint = "untilReceiverValue")
}
untilArgVar = scope.createTemporaryVariable(untilArgCasted, nameHint = "untilArg")
additionalVariables = listOfNotNull(receiverValueVar, untilArgVar)
}
val first = if (receiverValueVar == null) receiverValue else irGet(receiverValueVar)
val untilArgExpression = if (untilArgVar == null) untilArgCasted else irGet(untilArgVar)
val last = untilArgExpression.decrement()
val (minValueAsLong, minValueIrConst) =
when (data) {
ProgressionType.INT_PROGRESSION -> Pair(Int.MIN_VALUE.toLong(), irInt(Int.MIN_VALUE))
ProgressionType.CHAR_PROGRESSION -> Pair(Char.MIN_VALUE.toLong(), irChar(Char.MIN_VALUE))
ProgressionType.LONG_PROGRESSION -> Pair(Long.MIN_VALUE, irLong(Long.MIN_VALUE))
}
val additionalNotEmptyCondition = untilArg.constLongValue.let {
when {
it == null && isAdditionalNotEmptyConditionNeeded(receiverValue.type, untilArg.type) ->
// Condition is needed and untilArg is non-const.
// Build the additional "not empty" condition: `untilArg != MIN_VALUE`.
irNotEquals(untilArgExpression, minValueIrConst)
it == minValueAsLong ->
// Hardcode "false" as additional condition so that the progression is considered empty.
// The entire lowered loop becomes a candidate for dead code elimination, depending on backend.
irFalse()
else ->
// We know that untilArg != MIN_VALUE, so the additional condition is not necessary.
null
}
}
ProgressionHeaderInfo( ProgressionHeaderInfo(
data, data,
first = expression.extensionReceiver!!, first = first,
last = expression.getValueArgument(0)!!, last = last,
step = irInt(1), step = irInt(1),
isLastInclusive = false canOverflow = false,
additionalVariables = additionalVariables,
additionalNotEmptyCondition = additionalNotEmptyCondition,
direction = ProgressionDirection.INCREASING
) )
} }
private fun isAdditionalNotEmptyConditionNeeded(receiverType: IrType, argType: IrType): Boolean {
// Here are the available `until` extension functions:
//
// infix fun Char.until(to: Char): CharRange
// infix fun Byte.until(to: Byte): IntRange
// infix fun Byte.until(to: Short): IntRange
// infix fun Byte.until(to: Int): IntRange
// infix fun Byte.until(to: Long): LongRange
// infix fun Short.until(to: Byte): IntRange
// infix fun Short.until(to: Short): IntRange
// infix fun Short.until(to: Int): IntRange
// infix fun Short.until(to: Long): LongRange
// infix fun Int.until(to: Byte): IntRange
// infix fun Int.until(to: Short): IntRange
// infix fun Int.until(to: Int): IntRange
// infix fun Int.until(to: Long): LongRange
// infix fun Long.until(to: Byte): LongRange
// infix fun Long.until(to: Short): LongRange
// infix fun Long.until(to: Int): LongRange
// infix fun Long.until(to: Long): LongRange
//
// The combinations where the range element type is strictly larger than the argument type do NOT need the additional condition.
// In such combinations, there is no possibility of underflow when the argument (casted to the range element type) is decremented.
// For unexpected combinations that currently don't exist (e.g., Int until Char), we assume the check is needed to be safe.
// TODO: Include unsigned types
return with(context.irBuiltIns) {
when (receiverType) {
charType -> true
byteType, shortType, intType -> when (argType) {
byteType, shortType -> false
else -> true
}
longType -> when (argType) {
byteType, shortType, intType -> false
else -> true
}
else -> true
}
}
}
} }
/** Builds a [HeaderInfo] for progressions built using the `indices` extension property. */ /** Builds a [HeaderInfo] for progressions built using the `indices` extension property. */
internal class IndicesHandler(val context: CommonBackendContext) : ProgressionHandler { internal class IndicesHandler(private val context: CommonBackendContext) : ProgressionHandler {
override val matcher = SimpleCalleeMatcher { override val matcher = SimpleCalleeMatcher {
// TODO: Handle Collection<*>.indices // TODO: Handle Collection<*>.indices
// TODO: Handle CharSequence.indices // TODO: Handle CharSequence.indices
extensionReceiver { it != null && KotlinBuiltIns.isArrayOrPrimitiveArray(it.type.toKotlinType()) } extensionReceiver { it != null && it.type.run { isArray() || isPrimitiveArray() } }
fqName { it == FqName("kotlin.collections.<get-indices>") } fqName { it == FqName("kotlin.collections.<get-indices>") }
parameterCount { it == 0 } parameterCount { it == 0 }
} }
override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// `last = array.size` for the loop `for (i in array.indices)`. // `last = array.size - 1` (last is inclusive) for the loop `for (i in array.indices)`.
val arraySizeProperty = expression.extensionReceiver!!.type.getClass()!!.properties.first { it.name.asString() == "size" } val arraySizeProperty = expression.extensionReceiver!!.type.getClass()!!.properties.first { it.name.asString() == "size" }
val last = irCall(arraySizeProperty.getter!!).apply { val last = irCall(arraySizeProperty.getter!!).apply {
dispatchReceiver = expression.extensionReceiver dispatchReceiver = expression.extensionReceiver
} }.decrement()
ProgressionHeaderInfo( ProgressionHeaderInfo(
data, data,
first = irInt(0), first = irInt(0),
last = last, last = last,
step = irInt(1), step = irInt(1),
isLastInclusive = false canOverflow = false,
direction = ProgressionDirection.INCREASING
) )
} }
} }
/** Builds a [HeaderInfo] for calls to reverse an iterable. */ /** Builds a [HeaderInfo] for calls to reverse an iterable. */
internal class ReversedHandler(context: CommonBackendContext, val visitor: IrElementVisitor<HeaderInfo?, Nothing?>) : internal class ReversedHandler(context: CommonBackendContext, private val visitor: IrElementVisitor<HeaderInfo?, Nothing?>) :
HeaderInfoFromCallHandler<Nothing?> { HeaderInfoFromCallHandler<Nothing?> {
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
@@ -154,7 +284,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
// Directly use the `first/last/step` properties of the progression. // Directly use the `first/last/step` properties of the progression.
val progression = scope.createTemporaryVariable(expression) val progression = scope.createTemporaryVariable(expression, nameHint = "progression")
val progressionClass = progression.type.getClass()!! val progressionClass = progression.type.getClass()!!
val firstProperty = progressionClass.properties.first { it.name.asString() == "first" } val firstProperty = progressionClass.properties.first { it.name.asString() == "first" }
val first = irCall(firstProperty.getter!!).apply { val first = irCall(firstProperty.getter!!).apply {
@@ -174,7 +304,8 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
first, first,
last, last,
step, step,
additionalVariables = listOf(progression) additionalVariables = listOf(progression),
direction = ProgressionDirection.UNKNOWN
) )
} }
} }
@@ -182,7 +313,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
/** Builds a [HeaderInfo] for arrays. */ /** Builds a [HeaderInfo] for arrays. */
internal class ArrayIterationHandler(private val context: CommonBackendContext) : ExpressionHandler { internal class ArrayIterationHandler(private val context: CommonBackendContext) : ExpressionHandler {
override fun match(expression: IrExpression) = KotlinBuiltIns.isArrayOrPrimitiveArray(expression.type.toKotlinType()) override fun match(expression: IrExpression) = expression.type.run { isArray() || isPrimitiveArray() }
override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? = override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? =
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
@@ -206,7 +337,7 @@ internal class ArrayIterationHandler(private val context: CommonBackendContext)
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
) )
// `last = array.size` for the loop `for (i in array.indices)`. // `last = array.size` (last is exclusive) for the loop `for (i in array.indices)`.
val arraySizeProperty = arrayReference.type.getClass()!!.properties.first { it.name.asString() == "size" } val arraySizeProperty = arrayReference.type.getClass()!!.properties.first { it.name.asString() == "size" }
val last = irCall(arraySizeProperty.getter!!).apply { val last = irCall(arraySizeProperty.getter!!).apply {
dispatchReceiver = irGet(arrayReference) dispatchReceiver = irGet(arrayReference)
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.lower.loops
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
internal fun IrExpression.castIfNecessary(targetType: IrType, numberCastFunctionName: Name): IrExpression {
return if (type == targetType) {
this
} else {
val function = type.getClass()!!.functions.first { it.name == numberCastFunctionName }
IrCallImpl(startOffset, endOffset, function.returnType, function.symbol)
.apply { dispatchReceiver = this@castIfNecessary }
}
}
/** Return the negated value if the expression is const, otherwise call unaryMinus(). */
internal fun IrExpression.negate(): IrExpression {
val value = (this as? IrConst<*>)?.value as? Number
return when (value) {
is Int -> IrConstImpl(startOffset, endOffset, type, IrConstKind.Int, -value)
is Long -> IrConstImpl(startOffset, endOffset, type, IrConstKind.Long, -value)
else -> {
val unaryMinusFun = type.getClass()!!.functions.first { it.name == OperatorNameConventions.UNARY_MINUS }
IrCallImpl(startOffset, endOffset, type, unaryMinusFun.symbol, unaryMinusFun.descriptor).apply {
dispatchReceiver = this@negate
}
}
}
}
/** Return `this - 1` if the expression is const, otherwise call dec(). */
internal fun IrExpression.decrement(): IrExpression {
val thisValue = (this as? IrConst<*>)?.value
return when (thisValue) {
is Int -> IrConstImpl(startOffset, endOffset, type, IrConstKind.Int, thisValue - 1)
is Long -> IrConstImpl(startOffset, endOffset, type, IrConstKind.Long, thisValue - 1)
is Char -> IrConstImpl(startOffset, endOffset, type, IrConstKind.Char, thisValue - 1)
else -> {
val decFun = type.getClass()!!.functions.first { it.name == OperatorNameConventions.DEC }
IrCallImpl(startOffset, endOffset, type, decFun.symbol, decFun.descriptor).apply {
dispatchReceiver = this@decrement
}
}
}
}
internal val IrExpression.canHaveSideEffects: Boolean
get() = this !is IrConst<*> && this !is IrGetValue
internal val IrExpression.constLongValue: Long?
get() = if (this is IrConst<*>) {
val value = this.value
when (value) {
is Number -> value.toLong()
is Char -> value.toLong()
else -> null
}
} else null
@@ -7,10 +7,9 @@ package org.jetbrains.kotlin.backend.common.lower.matchers
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.SimpleType
internal interface IrFunctionMatcher : (IrFunction) -> Boolean internal interface IrFunctionMatcher : (IrFunction) -> Boolean
@@ -91,9 +90,9 @@ internal fun createIrFunctionRestrictions(restrictions: IrFunctionMatcherContain
internal fun IrFunctionMatcherContainer.singleArgumentExtension( internal fun IrFunctionMatcherContainer.singleArgumentExtension(
fqName: FqName, fqName: FqName,
types: Collection<SimpleType> types: Collection<IrType>
): IrFunctionMatcherContainer { ): IrFunctionMatcherContainer {
extensionReceiver { it != null && it.type.toKotlinType() in types } extensionReceiver { it != null && it.type in types }
parameterCount { it == 1 } parameterCount { it == 1 }
fqName { it == fqName } fqName { it == fqName }
return this return this
@@ -0,0 +1,21 @@
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME
import kotlin.test.*
val log = StringBuilder()
fun logged(message: String, value: Int) =
value.also { log.append(message) }
fun box(): String {
var sum = 0
for (i in (logged("start;", 4) downTo logged("end;", 1)).reversed().reversed()) {
sum = sum * 10 + i
}
assertEquals(4321, sum)
assertEquals("start;end;", log.toString())
return "OK"
}
@@ -0,0 +1,21 @@
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME
import kotlin.test.*
val log = StringBuilder()
fun logged(message: String, value: Int) =
value.also { log.append(message) }
fun box(): String {
var sum = 0
for (i in (logged("start;", 1)..logged("end;", 4)).reversed().reversed()) {
sum = sum * 10 + i
}
assertEquals(1234, sum)
assertEquals("start;end;", log.toString())
return "OK"
}
@@ -0,0 +1,21 @@
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME
import kotlin.test.*
val log = StringBuilder()
fun logged(message: String, value: Int) =
value.also { log.append(message) }
fun box(): String {
var sum = 0
for (i in (logged("start;", 1) until logged("end;", 5)).reversed().reversed()) {
sum = sum * 10 + i
}
assertEquals(1234, sum)
assertEquals("start;end;", log.toString())
return "OK"
}
@@ -3,7 +3,7 @@
import kotlin.test.assertEquals import kotlin.test.assertEquals
fun box(): String { fun box(): String {
for (ch in (-10).toChar() until '\u0000') { for (i in Char.MAX_VALUE until Char.MAX_VALUE) {
throw AssertionError("This loop shoud not be executed") throw AssertionError("This loop shoud not be executed")
} }
return "OK" return "OK"
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
for (ch in (-10).toChar() until Char.MIN_VALUE) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
var bound = Char.MIN_VALUE
for (ch in (-10).toChar() until bound) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
var bound = Int.MIN_VALUE
for (i in 0 until bound) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
for (i in Long.MAX_VALUE until Long.MAX_VALUE) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
var bound = Long.MIN_VALUE
for (i in 0 until bound) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
fun test() { fun test() {
var sum = 0 var sum = 0
for (i in arrayOf("", "", "", "").indices) { for (i in arrayOf("", "", "", "").indices) {
@@ -5,10 +6,20 @@ fun test() {
} }
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// JVM_TEMPLATES
// 1 IF_ICMPGE // 1 IF_ICMPGE
// 1 IF // 1 IF
// JVM_IR_TEMPLATES
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF
@@ -0,0 +1,19 @@
// TARGET_BACKEND: JVM_IR
fun test() {
var sum = 0
for (i in arrayOf("", "", "", "").indices) {
sum += i
}
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
fun test() { fun test() {
var sum = 0 var sum = 0
for (i in intArrayOf(0, 0, 0, 0).indices) { for (i in intArrayOf(0, 0, 0, 0).indices) {
@@ -5,6 +6,9 @@ fun test() {
} }
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,19 @@
// TARGET_BACKEND: JVM_IR
fun test() {
var sum = 0
for (i in intArrayOf(0, 0, 0, 0).indices) {
sum += i
}
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
const val N = 'Z' const val N = 'Z'
fun test(): Int { fun test(): Int {
@@ -8,6 +9,9 @@ fun test(): Int {
return sum return sum
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM_IR
const val N = 'Z'
fun test(): Int {
var sum = 0
for (i in 'A' .. N) {
sum += i.toInt()
}
return sum
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPLE
// 1 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
const val N = 42 const val N = 42
fun test(): Int { fun test(): Int {
@@ -8,6 +9,9 @@ fun test(): Int {
return sum return sum
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM_IR
const val N = 42
fun test(): Int {
var sum = 0
for (i in 1 .. N) {
sum += i
}
return sum
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPLE
// 1 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
const val N = 42L const val N = 42L
fun test(): Long { fun test(): Long {
@@ -8,6 +9,9 @@ fun test(): Long {
return sum return sum
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,26 @@
// TARGET_BACKEND: JVM_IR
const val N = 42L
fun test(): Long {
var sum = 0L
for (i in 1L .. N) {
sum += i
}
return sum
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 LCMP
// 1 IFGT
// 1 IFLE
// 2 IF
// 0 L2I
// 0 I2L
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
object Host { object Host {
const val M = 1 const val M = 1
const val N = 4 const val N = 4
@@ -11,6 +12,9 @@ fun test(): Int {
return s return s
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,25 @@
// TARGET_BACKEND: JVM_IR
object Host {
const val M = 1
const val N = 4
}
fun test(): Int {
var s = 0
for (i in Host.M .. Host.N) {
s += i
}
return s
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPLE
// 1 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.test.* import kotlin.test.*
fun box(): String { fun box(): String {
@@ -11,6 +12,9 @@ fun box(): String {
return "OK" return "OK"
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 reversed // 0 reversed
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
@@ -18,5 +22,5 @@ fun box(): String {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 1 IF(_ICMPG|L)T // 1 IFLT
// 1 IF // 1 IF
@@ -0,0 +1,27 @@
// TARGET_BACKEND: JVM_IR
import kotlin.test.*
fun box(): String {
val arr = intArrayOf(1, 1, 1, 1)
var sum = 0
for (i in arr.indices.reversed()) {
sum = sum * 10 + i + arr[i]
}
assertEquals(4321, sum)
return "OK"
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 reversed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.test.* import kotlin.test.*
fun box(): String { fun box(): String {
@@ -22,6 +23,9 @@ fun box(): String {
return "OK" return "OK"
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed // 0 reversed
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
@@ -29,7 +33,7 @@ fun box(): String {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 2 IF_ICMP[LG]T // 2 IF_ICMPGT
// 1 IF[LG]T // 1 IFGT
// 3 IF // 3 IF
// 1 LCMP // 1 LCMP
@@ -0,0 +1,40 @@
// TARGET_BACKEND: JVM_IR
import kotlin.test.*
fun box(): String {
var sum = 0
for (i in (4 downTo 1).reversed()) {
sum = sum * 10 + i
}
assertEquals(1234, sum)
var sumL = 0L
for (i in (4L downTo 1L).reversed()) {
sumL = sumL * 10 + i
}
assertEquals(1234L, sumL)
var sumC = 0
for (i in ('4' downTo '1').reversed()) {
sumC = sumC * 10 + i.toInt() - '0'.toInt()
}
assertEquals(1234, sumC)
return "OK"
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 IF_ICMPLE
// 1 IFGT
// 1 IFLE
// 4 IF
// 2 LCMP
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.test.* import kotlin.test.*
fun box(): String { fun box(): String {
@@ -22,6 +23,9 @@ fun box(): String {
return "OK" return "OK"
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed // 0 reversed
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
@@ -29,7 +33,7 @@ fun box(): String {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 2 IF_ICMP[LG]T // 2 IF_ICMPLT
// 1 IF[LG]T // 1 IFLT
// 3 IF // 3 IF
// 1 LCMP // 1 LCMP
@@ -0,0 +1,40 @@
// TARGET_BACKEND: JVM_IR
import kotlin.test.*
fun box(): String {
var sum = 0
for (i in (1 .. 4).reversed()) {
sum = sum * 10 + i
}
assertEquals(4321, sum)
var sumL = 0L
for (i in (1L .. 4L).reversed()) {
sumL = sumL * 10 + i
}
assertEquals(4321L, sumL)
var sumC = 0
for (i in ('1' .. '4').reversed()) {
sumC = sumC * 10 + i.toInt() - '0'.toInt()
}
assertEquals(4321, sumC)
return "OK"
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 IF_ICMPLE
// 1 IFGT
// 1 IFLE
// 4 IF
// 2 LCMP
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.test.* import kotlin.test.*
fun box(): String { fun box(): String {
@@ -22,6 +23,9 @@ fun box(): String {
return "OK" return "OK"
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed // 0 reversed
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
@@ -29,7 +33,7 @@ fun box(): String {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 2 IF_ICMP[LG]T // 2 IF_ICMPLT
// 1 IF[LG]T // 1 IFLT
// 3 IF // 3 IF
// 1 LCMP // 1 LCMP
@@ -0,0 +1,40 @@
// TARGET_BACKEND: JVM_IR
import kotlin.test.*
fun box(): String {
var sum = 0
for (i in (4 downTo 1).reversed().reversed()) {
sum = sum * 10 + i
}
assertEquals(1234, sum)
var sumL = 0L
for (i in (4L downTo 1L).reversed().reversed()) {
sumL = sumL * 10 + i
}
assertEquals(1234L, sumL)
var sumC = 0
for (i in ('4' downTo '1').reversed().reversed()) {
sumC = sumC * 10 + i.toInt() - '0'.toInt()
}
assertEquals(1234, sumC)
return "OK"
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 IF_ICMPLE
// 1 IFGT
// 1 IFLE
// 4 IF
// 2 LCMP
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.test.* import kotlin.test.*
fun box(): String { fun box(): String {
@@ -19,6 +20,9 @@ fun box(): String {
return "OK" return "OK"
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed // 0 reversed
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
@@ -26,7 +30,7 @@ fun box(): String {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 2 IF_ICMP[LG]E // 2 IF_ICMPGE
// 1 IF[LG]E // 1 IFGE
// 3 IF // 3 IF
// 1 LCMP // 1 LCMP
@@ -0,0 +1,37 @@
// TARGET_BACKEND: JVM_IR
import kotlin.test.*
fun box(): String {
var sum = 0
for (i in (1 until 5).reversed().reversed()) {
sum = sum * 10 + i
}
var sumL = 0L
for (i in (1L until 5L).reversed().reversed()) {
sumL = sumL * 10 + i
}
var sumC = 0
for (i in ('1' until '5').reversed().reversed()) {
sumC = sumC * 10 + i.toInt() - '0'.toInt()
}
return "OK"
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 IF_ICMPLE
// 1 IFGT
// 1 IFLE
// 4 IF
// 2 LCMP
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
import kotlin.test.* import kotlin.test.*
fun box(): String { fun box(): String {
@@ -19,6 +20,9 @@ fun box(): String {
return "OK" return "OK"
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed // 0 reversed
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
@@ -26,7 +30,7 @@ fun box(): String {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 2 IF_ICMP[LG]T // 2 IF_ICMPLT
// 1 IF[LG]T // 1 IFLT
// 3 IF // 3 IF
// 1 LCMP // 1 LCMP
@@ -0,0 +1,37 @@
// TARGET_BACKEND: JVM_IR
import kotlin.test.*
fun box(): String {
var sum = 0
for (i in (1 until 5).reversed()) {
sum = sum * 10 + i
}
var sumL = 0L
for (i in (1L until 5L).reversed()) {
sumL = sumL * 10 + i
}
var sumC = 0
for (i in ('1' until '5').reversed()) {
sumC = sumC * 10 + i.toInt() - '0'.toInt()
}
return "OK"
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long.
// 0 reversed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 IF_ICMPLE
// 1 IFGT
// 1 IFLE
// 4 IF
// 2 LCMP
@@ -0,0 +1,20 @@
// IGNORE_BACKEND: JVM_IR
fun test(a: Char, b: Char): String {
var s = ""
for (i in a until b) {
s += i
}
return s
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. In addition, for "until" progressions, there is a check that the range is not empty: upper bound != MIN_VALUE.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPGE
// 1 IF
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM_IR
fun test(a: Char, b: Char): String {
var s = ""
for (i in a until b) {
s += i
}
return s
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. In addition, for "until" progressions, there is a check that the range is not empty: upper bound != MIN_VALUE.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IFEQ
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 3 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
const val M = Char.MAX_VALUE const val M = Char.MAX_VALUE
fun f(a: Char): Int { fun f(a: Char): Int {
@@ -8,6 +9,9 @@ fun f(a: Char): Int {
return n return n
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,23 @@
// TARGET_BACKEND: JVM_IR
const val M = Char.MAX_VALUE
fun f(a: Char): Int {
var n = 0
for (i in a until M) {
n++
}
return n
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM_IR
const val M = Char.MIN_VALUE
fun f(a: Char): Int {
var n = 0
for (i in a until M) {
n++
}
return n
}
// For "until" progressions in JVM IR, there is a check that the range is not empty: upper bound != MIN_VALUE.
// When the upper bound == const MIN_VALUE, the backend can eliminate the entire loop as dead code.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 0 IF
// 0 LINENUMBER 7
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
fun test(a: Int, b: Int): Int { fun test(a: Int, b: Int): Int {
var sum = 0 var sum = 0
for (i in a until b) { for (i in a until b) {
@@ -6,6 +7,9 @@ fun test(a: Int, b: Int): Int {
return sum return sum
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. In addition, for "until" progressions, there is a check that the range is not empty: upper bound != MIN_VALUE.
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,23 @@
// TARGET_BACKEND: JVM_IR
fun test(a: Int, b: Int): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. In addition, for "until" progressions, there is a check that the range is not empty: upper bound != MIN_VALUE.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 LDC -2147483648
// 1 IF_ICMPEQ
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 3 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
const val M = Int.MAX_VALUE const val M = Int.MAX_VALUE
fun f(a: Int): Int { fun f(a: Int): Int {
@@ -8,6 +9,9 @@ fun f(a: Int): Int {
return n return n
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,23 @@
// TARGET_BACKEND: JVM_IR
const val M = Int.MAX_VALUE
fun f(a: Int): Int {
var n = 0
for (i in a until M) {
n++
}
return n
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPGT
// 1 IF_ICMPLE
// 2 IF
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM_IR
const val M = Int.MIN_VALUE
fun f(a: Int): Int {
var n = 0
for (i in a until M) {
n++
}
return n
}
// For "until" progressions in JVM IR, there is a check that the range is not empty: upper bound != MIN_VALUE.
// When the upper bound == const MIN_VALUE, the backend can eliminate the entire loop as dead code.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 0 IF
// 0 LINENUMBER 7
@@ -0,0 +1,21 @@
// IGNORE_BACKEND: JVM_IR
fun test(a: Long, b: Long): Long {
var sum = 0L
for (i in a until b) {
sum = sum * 10L + i
}
return sum
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. In addition, for "until" progressions, there is a check that the range is not empty: upper bound != MIN_VALUE.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 LCMP
// 1 IFGE
// 1 IF
@@ -0,0 +1,24 @@
// TARGET_BACKEND: JVM_IR
fun test(a: Long, b: Long): Long {
var sum = 0L
for (i in a until b) {
sum = sum * 10L + i
}
return sum
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. In addition, for "until" progressions, there is a check that the range is not empty: upper bound != MIN_VALUE.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 LDC -9223372036854775808
// 3 LCMP
// 1 IFEQ
// 1 IFGT
// 1 IFLE
// 3 IF
@@ -1,3 +1,4 @@
// IGNORE_BACKEND: JVM_IR
const val M = Long.MAX_VALUE const val M = Long.MAX_VALUE
fun f(a: Long): Int { fun f(a: Long): Int {
@@ -8,6 +9,9 @@ fun f(a: Long): Int {
return n return n
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,24 @@
// TARGET_BACKEND: JVM_IR
const val M = Long.MAX_VALUE
fun f(a: Long): Int {
var n = 0
for (i in a until M) {
n++
}
return n
}
// JVM non-IR uses while.
// JVM IR uses if + do-while.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 LCMP
// 1 IFGT
// 1 IFLE
// 2 IF
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM_IR
const val M = Long.MIN_VALUE
fun f(a: Long): Int {
var n = 0
for (i in a until M) {
n++
}
return n
}
// For "until" progressions in JVM IR, there is a check that the range is not empty: upper bound != MIN_VALUE.
// When the upper bound == const MIN_VALUE, the backend can eliminate the entire loop as dead code.
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 0 IF
// 0 LINENUMBER 7
@@ -0,0 +1,41 @@
// TARGET_BACKEND: JVM_IR
fun testByteUntilInt(a: Byte, b: Int): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
fun testShortUntilInt(a: Short, b: Int): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
// For "until" progressions in JVM IR, there is typically a check that the range is not empty: upper bound != MIN_VALUE.
// However, this check is not needed when the upper bound is smaller than the range element type.
// Here are the available `until` extension functions with mixed bounds that return IntRange:
//
// infix fun Byte.until(to: Byte): IntRange
// infix fun Byte.until(to: Short): IntRange
// infix fun Byte.until(to: Int): IntRange // Bound check needed
// infix fun Short.until(to: Byte): IntRange
// infix fun Short.until(to: Short): IntRange
// infix fun Short.until(to: Int): IntRange // Bound check needed
// infix fun Int.until(to: Byte): IntRange
// infix fun Int.until(to: Short): IntRange
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 LDC -2147483648
// 2 IF_ICMPEQ
// 2 IF_ICMPGT
// 2 IF_ICMPLE
// 6 IF
@@ -0,0 +1,72 @@
// TARGET_BACKEND: JVM_IR
fun testByteUntilByte(a: Byte, b: Byte): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
fun testByteUntilShort(a: Byte, b: Short): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
fun testShortUntilByte(a: Short, b: Byte): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
fun testShortUntilShort(a: Short, b: Short): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
fun testIntUntilByte(a: Int, b: Byte): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
fun testIntUntilShort(a: Int, b: Short): Int {
var sum = 0
for (i in a until b) {
sum = sum * 10 + i
}
return sum
}
// For "until" progressions in JVM IR, there is typically a check that the range is not empty: upper bound != MIN_VALUE.
// However, this check is not needed when the upper bound is smaller than the range element type.
// Here are the available `until` extension functions with mixed bounds that return IntRange:
//
// infix fun Byte.until(to: Byte): IntRange // NO bound check needed
// infix fun Byte.until(to: Short): IntRange // NO bound check needed
// infix fun Byte.until(to: Int): IntRange
// infix fun Short.until(to: Byte): IntRange // NO bound check needed
// infix fun Short.until(to: Short): IntRange // NO bound check needed
// infix fun Short.until(to: Int): IntRange
// infix fun Int.until(to: Byte): IntRange // NO bound check needed
// infix fun Int.until(to: Short): IntRange // NO bound check needed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 0 LDC -2147483648
// 6 IF_ICMPGT
// 6 IF_ICMPLE
// 12 IF
@@ -0,0 +1,44 @@
// TARGET_BACKEND: JVM_IR
fun testLongUntilByte(a: Long, b: Byte): Long {
var sum = 0L
for (i in a until b) {
sum = sum * 10L + i
}
return sum
}
fun testLongUntilShort(a: Long, b: Short): Long {
var sum = 0L
for (i in a until b) {
sum = sum * 10L + i
}
return sum
}
fun testLongUntilInt(a: Long, b: Int): Long {
var sum = 0L
for (i in a until b) {
sum = sum * 10L + i
}
return sum
}
// For "until" progressions in JVM IR, there is typically a check that the range is not empty: upper bound != MIN_VALUE.
// However, this check is not needed when the upper bound is smaller than the range element type.
// Here are the available `until` extension functions with mixed bounds that return LongRange:
//
// infix fun Long.until(to: Byte): LongRange // NO bound check needed
// infix fun Long.until(to: Short): LongRange // NO bound check needed
// infix fun Long.until(to: Int): LongRange // NO bound check needed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 0 LDC -9223372036854775808
// 6 LCMP
// 3 IFGT
// 3 IFLE
// 6 IF
@@ -1,8 +1,12 @@
// IGNORE_BACKEND: JVM_IR
fun f() { fun f() {
for (i in 1..2) { for (i in 1..2) {
} }
} }
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator // 0 iterator
// 0 getStart // 0 getStart
// 0 getEnd // 0 getEnd
@@ -0,0 +1,17 @@
// TARGET_BACKEND: JVM_IR
fun f() {
for (i in 1..2) {
}
}
// JVM non-IR uses while.
// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition).
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 1 IF_ICMPLE
// 1 IF
@@ -18867,34 +18867,49 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
} }
@TestMetadata("forInDownToEvaluationOrder.kt") @TestMetadata("forInDownTo.kt")
public void testForInDownToEvaluationOrder() throws Exception { public void testForInDownTo() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownTo.kt");
} }
@TestMetadata("forInRangeLiteralEvaluationOrder.kt") @TestMetadata("forInDownToReversed.kt")
public void testForInRangeLiteralEvaluationOrder() throws Exception { public void testForInDownToReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversed.kt");
} }
@TestMetadata("forInReversedDownToEvaluationOrder.kt") @TestMetadata("forInDownToReversedReversed.kt")
public void testForInReversedDownToEvaluationOrder() throws Exception { public void testForInDownToReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversedReversed.kt");
} }
@TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") @TestMetadata("forInRangeLiteral.kt")
public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { public void testForInRangeLiteral() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteral.kt");
} }
@TestMetadata("forInReversedUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversed.kt")
public void testForInReversedUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversed.kt");
} }
@TestMetadata("forInUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversedReversed.kt")
public void testForInUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversedReversed.kt");
}
@TestMetadata("forInUntil.kt")
public void testForInUntil() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntil.kt");
}
@TestMetadata("forInUntilReversed.kt")
public void testForInUntilReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversed.kt");
}
@TestMetadata("forInUntilReversedReversed.kt")
public void testForInUntilReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversedReversed.kt");
} }
} }
@@ -19312,9 +19327,19 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt");
} }
@TestMetadata("forInUntilChar0.kt") @TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilChar0() throws Exception { public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilCharMinValue.kt")
public void testForInUntilCharMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValue.kt");
}
@TestMetadata("forInUntilCharMinValueNonConst.kt")
public void testForInUntilCharMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValueNonConst.kt");
} }
@TestMetadata("forInUntilInt.kt") @TestMetadata("forInUntilInt.kt")
@@ -19322,6 +19347,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt");
} }
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilIntMinValue.kt")
public void testForInUntilIntMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValue.kt");
}
@TestMetadata("forInUntilIntMinValueNonConst.kt")
public void testForInUntilIntMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValueNonConst.kt");
}
@TestMetadata("forInUntilLesserInt.kt") @TestMetadata("forInUntilLesserInt.kt")
public void testForInUntilLesserInt() throws Exception { public void testForInUntilLesserInt() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt");
@@ -19332,19 +19372,19 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt");
} }
@TestMetadata("forInUntilMaxint.kt") @TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilMaxint() throws Exception { public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMaxint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMaxValue.kt");
} }
@TestMetadata("forInUntilMinint.kt") @TestMetadata("forInUntilLongMinValue.kt")
public void testForInUntilMinint() throws Exception { public void testForInUntilLongMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValue.kt");
} }
@TestMetadata("forInUntilMinlong.kt") @TestMetadata("forInUntilLongMinValueNonConst.kt")
public void testForInUntilMinlong() throws Exception { public void testForInUntilLongMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinlong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValueNonConst.kt");
} }
@TestMetadata("forIntInIntUntilSmartcastInt.kt") @TestMetadata("forIntInIntUntilSmartcastInt.kt")
@@ -1742,26 +1742,6 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt");
} }
@TestMetadata("forInUntil.kt")
public void testForInUntil() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil.kt");
}
@TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntilLongMaxValue.kt");
}
@TestMetadata("forIntInDownTo.kt") @TestMetadata("forIntInDownTo.kt")
public void testForIntInDownTo() throws Exception { public void testForIntInDownTo() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt");
@@ -2079,6 +2059,49 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt");
} }
} }
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInUntil")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ForInUntil extends AbstractBytecodeTextTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInForInUntil() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/forLoop/forInUntil"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("forInUntilChar.kt")
public void testForInUntilChar() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilChar.kt");
}
@TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilInt.kt")
public void testForInUntilInt() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilInt.kt");
}
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilLong.kt")
public void testForInUntilLong() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLong.kt");
}
@TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMaxValue.kt");
}
}
} }
@TestMetadata("compiler/testData/codegen/bytecodeText/hashCode") @TestMetadata("compiler/testData/codegen/bytecodeText/hashCode")
@@ -18867,34 +18867,49 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
} }
@TestMetadata("forInDownToEvaluationOrder.kt") @TestMetadata("forInDownTo.kt")
public void testForInDownToEvaluationOrder() throws Exception { public void testForInDownTo() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownTo.kt");
} }
@TestMetadata("forInRangeLiteralEvaluationOrder.kt") @TestMetadata("forInDownToReversed.kt")
public void testForInRangeLiteralEvaluationOrder() throws Exception { public void testForInDownToReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversed.kt");
} }
@TestMetadata("forInReversedDownToEvaluationOrder.kt") @TestMetadata("forInDownToReversedReversed.kt")
public void testForInReversedDownToEvaluationOrder() throws Exception { public void testForInDownToReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversedReversed.kt");
} }
@TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") @TestMetadata("forInRangeLiteral.kt")
public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { public void testForInRangeLiteral() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteral.kt");
} }
@TestMetadata("forInReversedUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversed.kt")
public void testForInReversedUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversed.kt");
} }
@TestMetadata("forInUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversedReversed.kt")
public void testForInUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversedReversed.kt");
}
@TestMetadata("forInUntil.kt")
public void testForInUntil() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntil.kt");
}
@TestMetadata("forInUntilReversed.kt")
public void testForInUntilReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversed.kt");
}
@TestMetadata("forInUntilReversedReversed.kt")
public void testForInUntilReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversedReversed.kt");
} }
} }
@@ -19312,9 +19327,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt");
} }
@TestMetadata("forInUntilChar0.kt") @TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilChar0() throws Exception { public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilCharMinValue.kt")
public void testForInUntilCharMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValue.kt");
}
@TestMetadata("forInUntilCharMinValueNonConst.kt")
public void testForInUntilCharMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValueNonConst.kt");
} }
@TestMetadata("forInUntilInt.kt") @TestMetadata("forInUntilInt.kt")
@@ -19322,6 +19347,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt");
} }
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilIntMinValue.kt")
public void testForInUntilIntMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValue.kt");
}
@TestMetadata("forInUntilIntMinValueNonConst.kt")
public void testForInUntilIntMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValueNonConst.kt");
}
@TestMetadata("forInUntilLesserInt.kt") @TestMetadata("forInUntilLesserInt.kt")
public void testForInUntilLesserInt() throws Exception { public void testForInUntilLesserInt() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt");
@@ -19332,19 +19372,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt");
} }
@TestMetadata("forInUntilMaxint.kt") @TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilMaxint() throws Exception { public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMaxint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMaxValue.kt");
} }
@TestMetadata("forInUntilMinint.kt") @TestMetadata("forInUntilLongMinValue.kt")
public void testForInUntilMinint() throws Exception { public void testForInUntilLongMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValue.kt");
} }
@TestMetadata("forInUntilMinlong.kt") @TestMetadata("forInUntilLongMinValueNonConst.kt")
public void testForInUntilMinlong() throws Exception { public void testForInUntilLongMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinlong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValueNonConst.kt");
} }
@TestMetadata("forIntInIntUntilSmartcastInt.kt") @TestMetadata("forIntInIntUntilSmartcastInt.kt")
@@ -17757,34 +17757,49 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
} }
@TestMetadata("forInDownToEvaluationOrder.kt") @TestMetadata("forInDownTo.kt")
public void testForInDownToEvaluationOrder() throws Exception { public void testForInDownTo() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownTo.kt");
} }
@TestMetadata("forInRangeLiteralEvaluationOrder.kt") @TestMetadata("forInDownToReversed.kt")
public void testForInRangeLiteralEvaluationOrder() throws Exception { public void testForInDownToReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversed.kt");
} }
@TestMetadata("forInReversedDownToEvaluationOrder.kt") @TestMetadata("forInDownToReversedReversed.kt")
public void testForInReversedDownToEvaluationOrder() throws Exception { public void testForInDownToReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversedReversed.kt");
} }
@TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") @TestMetadata("forInRangeLiteral.kt")
public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { public void testForInRangeLiteral() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteral.kt");
} }
@TestMetadata("forInReversedUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversed.kt")
public void testForInReversedUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversed.kt");
} }
@TestMetadata("forInUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversedReversed.kt")
public void testForInUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversedReversed.kt");
}
@TestMetadata("forInUntil.kt")
public void testForInUntil() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntil.kt");
}
@TestMetadata("forInUntilReversed.kt")
public void testForInUntilReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversed.kt");
}
@TestMetadata("forInUntilReversedReversed.kt")
public void testForInUntilReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversedReversed.kt");
} }
} }
@@ -18202,9 +18217,19 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt");
} }
@TestMetadata("forInUntilChar0.kt") @TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilChar0() throws Exception { public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilCharMinValue.kt")
public void testForInUntilCharMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValue.kt");
}
@TestMetadata("forInUntilCharMinValueNonConst.kt")
public void testForInUntilCharMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValueNonConst.kt");
} }
@TestMetadata("forInUntilInt.kt") @TestMetadata("forInUntilInt.kt")
@@ -18212,6 +18237,21 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt");
} }
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilIntMinValue.kt")
public void testForInUntilIntMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValue.kt");
}
@TestMetadata("forInUntilIntMinValueNonConst.kt")
public void testForInUntilIntMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValueNonConst.kt");
}
@TestMetadata("forInUntilLesserInt.kt") @TestMetadata("forInUntilLesserInt.kt")
public void testForInUntilLesserInt() throws Exception { public void testForInUntilLesserInt() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt");
@@ -18222,19 +18262,19 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt");
} }
@TestMetadata("forInUntilMaxint.kt") @TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilMaxint() throws Exception { public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMaxint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMaxValue.kt");
} }
@TestMetadata("forInUntilMinint.kt") @TestMetadata("forInUntilLongMinValue.kt")
public void testForInUntilMinint() throws Exception { public void testForInUntilLongMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValue.kt");
} }
@TestMetadata("forInUntilMinlong.kt") @TestMetadata("forInUntilLongMinValueNonConst.kt")
public void testForInUntilMinlong() throws Exception { public void testForInUntilLongMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinlong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValueNonConst.kt");
} }
@TestMetadata("forIntInIntUntilSmartcastInt.kt") @TestMetadata("forIntInIntUntilSmartcastInt.kt")
@@ -1657,6 +1657,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharConst.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharConst.kt");
} }
@TestMetadata("forInRangeToCharConstIR.kt")
public void testForInRangeToCharConstIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharConstIR.kt");
}
@TestMetadata("forInRangeToCharMaxValue.kt") @TestMetadata("forInRangeToCharMaxValue.kt")
public void testForInRangeToCharMaxValue() throws Exception { public void testForInRangeToCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharMaxValue.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharMaxValue.kt");
@@ -1667,6 +1672,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToConst.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToConst.kt");
} }
@TestMetadata("forInRangeToConstIR.kt")
public void testForInRangeToConstIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToConstIR.kt");
}
@TestMetadata("forInRangeToIntMaxValue.kt") @TestMetadata("forInRangeToIntMaxValue.kt")
public void testForInRangeToIntMaxValue() throws Exception { public void testForInRangeToIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToIntMaxValue.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToIntMaxValue.kt");
@@ -1677,6 +1687,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongConst.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongConst.kt");
} }
@TestMetadata("forInRangeToLongConstIR.kt")
public void testForInRangeToLongConstIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongConstIR.kt");
}
@TestMetadata("forInRangeToLongMaxValue.kt") @TestMetadata("forInRangeToLongMaxValue.kt")
public void testForInRangeToLongMaxValue() throws Exception { public void testForInRangeToLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongMaxValue.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongMaxValue.kt");
@@ -1687,6 +1702,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToQualifiedConst.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToQualifiedConst.kt");
} }
@TestMetadata("forInRangeToQualifiedConstIR.kt")
public void testForInRangeToQualifiedConstIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeToQualifiedConstIR.kt");
}
@TestMetadata("forInRangeWithImplicitReceiver.kt") @TestMetadata("forInRangeWithImplicitReceiver.kt")
public void testForInRangeWithImplicitReceiver() throws Exception { public void testForInRangeWithImplicitReceiver() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithImplicitReceiver.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithImplicitReceiver.kt");
@@ -1697,26 +1717,6 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInStringSpecialized.kt");
} }
@TestMetadata("forInUntil.kt")
public void testForInUntil() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil.kt");
}
@TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntilLongMaxValue.kt");
}
@TestMetadata("forIntInDownTo.kt") @TestMetadata("forIntInDownTo.kt")
public void testForIntInDownTo() throws Exception { public void testForIntInDownTo() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt");
@@ -1737,6 +1737,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt");
} }
@TestMetadata("primitiveLiteralRange1IR.kt")
public void testPrimitiveLiteralRange1IR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1IR.kt");
}
@TestMetadata("primitiveLiteralRange2.kt") @TestMetadata("primitiveLiteralRange2.kt")
public void testPrimitiveLiteralRange2() throws Exception { public void testPrimitiveLiteralRange2() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange2.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange2.kt");
@@ -1870,10 +1875,20 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInObjectArrayIndices.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInObjectArrayIndices.kt");
} }
@TestMetadata("forInObjectArrayIndicesIR.kt")
public void testForInObjectArrayIndicesIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInObjectArrayIndicesIR.kt");
}
@TestMetadata("forInPrimitiveArrayIndices.kt") @TestMetadata("forInPrimitiveArrayIndices.kt")
public void testForInPrimitiveArrayIndices() throws Exception { public void testForInPrimitiveArrayIndices() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInPrimitiveArrayIndices.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInPrimitiveArrayIndices.kt");
} }
@TestMetadata("forInPrimitiveArrayIndicesIR.kt")
public void testForInPrimitiveArrayIndicesIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInPrimitiveArrayIndicesIR.kt");
}
} }
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInIterableWithIndex") @TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInIterableWithIndex")
@@ -1931,6 +1946,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedArrayIndices.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedArrayIndices.kt");
} }
@TestMetadata("forInReversedArrayIndicesIR.kt")
public void testForInReversedArrayIndicesIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedArrayIndicesIR.kt");
}
@TestMetadata("forInReversedCharSequenceIndices.kt") @TestMetadata("forInReversedCharSequenceIndices.kt")
public void testForInReversedCharSequenceIndices() throws Exception { public void testForInReversedCharSequenceIndices() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCharSequenceIndices.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCharSequenceIndices.kt");
@@ -1946,6 +1966,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedDownTo.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedDownTo.kt");
} }
@TestMetadata("forInReversedDownToIR.kt")
public void testForInReversedDownToIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedDownToIR.kt");
}
@TestMetadata("forInReversedEmptyRangeLiteral.kt") @TestMetadata("forInReversedEmptyRangeLiteral.kt")
public void testForInReversedEmptyRangeLiteral() throws Exception { public void testForInReversedEmptyRangeLiteral() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedEmptyRangeLiteral.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedEmptyRangeLiteral.kt");
@@ -1961,6 +1986,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedRangeLiteral.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedRangeLiteral.kt");
} }
@TestMetadata("forInReversedRangeLiteralIR.kt")
public void testForInReversedRangeLiteralIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedRangeLiteralIR.kt");
}
@TestMetadata("forInReversedReversedArrayIndices.kt") @TestMetadata("forInReversedReversedArrayIndices.kt")
public void testForInReversedReversedArrayIndices() throws Exception { public void testForInReversedReversedArrayIndices() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedArrayIndices.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedArrayIndices.kt");
@@ -1971,6 +2001,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedDownTo.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedDownTo.kt");
} }
@TestMetadata("forInReversedReversedDownToIR.kt")
public void testForInReversedReversedDownToIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedDownToIR.kt");
}
@TestMetadata("ForInReversedReversedRange.kt") @TestMetadata("ForInReversedReversedRange.kt")
public void testForInReversedReversedRange() throws Exception { public void testForInReversedReversedRange() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/ForInReversedReversedRange.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/ForInReversedReversedRange.kt");
@@ -1986,10 +2021,20 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedUntil.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedUntil.kt");
} }
@TestMetadata("forInReversedReversedUntilIR.kt")
public void testForInReversedReversedUntilIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedReversedUntilIR.kt");
}
@TestMetadata("forInReversedUntil.kt") @TestMetadata("forInReversedUntil.kt")
public void testForInReversedUntil() throws Exception { public void testForInReversedUntil() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedUntil.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedUntil.kt");
} }
@TestMetadata("forInReversedUntilIR.kt")
public void testForInReversedUntilIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedUntilIR.kt");
}
} }
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex") @TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex")
@@ -2034,6 +2079,109 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt"); runTest("compiler/testData/codegen/bytecodeText/forLoop/forInSequenceWithIndex/forInSequenceWithIndexWithExplicitlyTypedIndexVariable.kt");
} }
} }
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInUntil")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ForInUntil extends AbstractIrBytecodeTextTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInForInUntil() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/forLoop/forInUntil"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("forInUntilChar.kt")
public void testForInUntilChar() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilChar.kt");
}
@TestMetadata("forInUntilCharIR.kt")
public void testForInUntilCharIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharIR.kt");
}
@TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilCharMaxValueIR.kt")
public void testForInUntilCharMaxValueIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMaxValueIR.kt");
}
@TestMetadata("forInUntilCharMinValueIR.kt")
public void testForInUntilCharMinValueIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMinValueIR.kt");
}
@TestMetadata("forInUntilInt.kt")
public void testForInUntilInt() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilInt.kt");
}
@TestMetadata("forInUntilIntIR.kt")
public void testForInUntilIntIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntIR.kt");
}
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilIntMaxValueIR.kt")
public void testForInUntilIntMaxValueIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMaxValueIR.kt");
}
@TestMetadata("forInUntilIntMinValueIR.kt")
public void testForInUntilIntMinValueIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMinValueIR.kt");
}
@TestMetadata("forInUntilLong.kt")
public void testForInUntilLong() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLong.kt");
}
@TestMetadata("forInUntilLongIR.kt")
public void testForInUntilLongIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongIR.kt");
}
@TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMaxValue.kt");
}
@TestMetadata("forInUntilLongMaxValueIR.kt")
public void testForInUntilLongMaxValueIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMaxValueIR.kt");
}
@TestMetadata("forInUntilLongMinValueIR.kt")
public void testForInUntilLongMinValueIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMinValueIR.kt");
}
@TestMetadata("forInUntilWithMixedTypeBoundsBoundCheckNeededForIntRangeIR.kt")
public void testForInUntilWithMixedTypeBoundsBoundCheckNeededForIntRangeIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilWithMixedTypeBoundsBoundCheckNeededForIntRangeIR.kt");
}
@TestMetadata("forInUntilWithMixedTypeBoundsNoBoundCheckNeededForIntRangeIR.kt")
public void testForInUntilWithMixedTypeBoundsNoBoundCheckNeededForIntRangeIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilWithMixedTypeBoundsNoBoundCheckNeededForIntRangeIR.kt");
}
@TestMetadata("forInUntilWithMixedTypeBoundsNoBoundCheckNeededForLongRangeIR.kt")
public void testForInUntilWithMixedTypeBoundsNoBoundCheckNeededForLongRangeIR() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilWithMixedTypeBoundsNoBoundCheckNeededForLongRangeIR.kt");
}
}
} }
@TestMetadata("compiler/testData/codegen/bytecodeText/hashCode") @TestMetadata("compiler/testData/codegen/bytecodeText/hashCode")
@@ -14802,34 +14802,49 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
} }
@TestMetadata("forInDownToEvaluationOrder.kt") @TestMetadata("forInDownTo.kt")
public void testForInDownToEvaluationOrder() throws Exception { public void testForInDownTo() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownTo.kt");
} }
@TestMetadata("forInRangeLiteralEvaluationOrder.kt") @TestMetadata("forInDownToReversed.kt")
public void testForInRangeLiteralEvaluationOrder() throws Exception { public void testForInDownToReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversed.kt");
} }
@TestMetadata("forInReversedDownToEvaluationOrder.kt") @TestMetadata("forInDownToReversedReversed.kt")
public void testForInReversedDownToEvaluationOrder() throws Exception { public void testForInDownToReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversedReversed.kt");
} }
@TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") @TestMetadata("forInRangeLiteral.kt")
public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { public void testForInRangeLiteral() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteral.kt");
} }
@TestMetadata("forInReversedUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversed.kt")
public void testForInReversedUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversed.kt");
} }
@TestMetadata("forInUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversedReversed.kt")
public void testForInUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversedReversed.kt");
}
@TestMetadata("forInUntil.kt")
public void testForInUntil() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntil.kt");
}
@TestMetadata("forInUntilReversed.kt")
public void testForInUntilReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversed.kt");
}
@TestMetadata("forInUntilReversedReversed.kt")
public void testForInUntilReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversedReversed.kt");
} }
} }
@@ -15247,9 +15262,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt");
} }
@TestMetadata("forInUntilChar0.kt") @TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilChar0() throws Exception { public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilCharMinValue.kt")
public void testForInUntilCharMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValue.kt");
}
@TestMetadata("forInUntilCharMinValueNonConst.kt")
public void testForInUntilCharMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValueNonConst.kt");
} }
@TestMetadata("forInUntilInt.kt") @TestMetadata("forInUntilInt.kt")
@@ -15257,6 +15282,21 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt");
} }
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilIntMinValue.kt")
public void testForInUntilIntMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValue.kt");
}
@TestMetadata("forInUntilIntMinValueNonConst.kt")
public void testForInUntilIntMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValueNonConst.kt");
}
@TestMetadata("forInUntilLesserInt.kt") @TestMetadata("forInUntilLesserInt.kt")
public void testForInUntilLesserInt() throws Exception { public void testForInUntilLesserInt() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt");
@@ -15267,19 +15307,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt");
} }
@TestMetadata("forInUntilMaxint.kt") @TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilMaxint() throws Exception { public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMaxint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMaxValue.kt");
} }
@TestMetadata("forInUntilMinint.kt") @TestMetadata("forInUntilLongMinValue.kt")
public void testForInUntilMinint() throws Exception { public void testForInUntilLongMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValue.kt");
} }
@TestMetadata("forInUntilMinlong.kt") @TestMetadata("forInUntilLongMinValueNonConst.kt")
public void testForInUntilMinlong() throws Exception { public void testForInUntilLongMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinlong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValueNonConst.kt");
} }
@TestMetadata("forIntInIntUntilSmartcastInt.kt") @TestMetadata("forIntInIntUntilSmartcastInt.kt")
@@ -15957,34 +15957,49 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/evaluationOrder"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
} }
@TestMetadata("forInDownToEvaluationOrder.kt") @TestMetadata("forInDownTo.kt")
public void testForInDownToEvaluationOrder() throws Exception { public void testForInDownTo() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownTo.kt");
} }
@TestMetadata("forInRangeLiteralEvaluationOrder.kt") @TestMetadata("forInDownToReversed.kt")
public void testForInRangeLiteralEvaluationOrder() throws Exception { public void testForInDownToReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversed.kt");
} }
@TestMetadata("forInReversedDownToEvaluationOrder.kt") @TestMetadata("forInDownToReversedReversed.kt")
public void testForInReversedDownToEvaluationOrder() throws Exception { public void testForInDownToReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedDownToEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInDownToReversedReversed.kt");
} }
@TestMetadata("forInReversedRangeLiteralEvaluationOrder.kt") @TestMetadata("forInRangeLiteral.kt")
public void testForInReversedRangeLiteralEvaluationOrder() throws Exception { public void testForInRangeLiteral() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedRangeLiteralEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteral.kt");
} }
@TestMetadata("forInReversedUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversed.kt")
public void testForInReversedUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInReversedUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversed.kt");
} }
@TestMetadata("forInUntilEvaluationOrder.kt") @TestMetadata("forInRangeLiteralReversedReversed.kt")
public void testForInUntilEvaluationOrder() throws Exception { public void testForInRangeLiteralReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilEvaluationOrder.kt"); runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInRangeLiteralReversedReversed.kt");
}
@TestMetadata("forInUntil.kt")
public void testForInUntil() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntil.kt");
}
@TestMetadata("forInUntilReversed.kt")
public void testForInUntilReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversed.kt");
}
@TestMetadata("forInUntilReversedReversed.kt")
public void testForInUntilReversedReversed() throws Exception {
runTest("compiler/testData/codegen/box/ranges/evaluationOrder/forInUntilReversedReversed.kt");
} }
} }
@@ -16402,9 +16417,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar.kt");
} }
@TestMetadata("forInUntilChar0.kt") @TestMetadata("forInUntilCharMaxValue.kt")
public void testForInUntilChar0() throws Exception { public void testForInUntilCharMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMaxValue.kt");
}
@TestMetadata("forInUntilCharMinValue.kt")
public void testForInUntilCharMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValue.kt");
}
@TestMetadata("forInUntilCharMinValueNonConst.kt")
public void testForInUntilCharMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilCharMinValueNonConst.kt");
} }
@TestMetadata("forInUntilInt.kt") @TestMetadata("forInUntilInt.kt")
@@ -16412,6 +16437,21 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilInt.kt");
} }
@TestMetadata("forInUntilIntMaxValue.kt")
public void testForInUntilIntMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMaxValue.kt");
}
@TestMetadata("forInUntilIntMinValue.kt")
public void testForInUntilIntMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValue.kt");
}
@TestMetadata("forInUntilIntMinValueNonConst.kt")
public void testForInUntilIntMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilIntMinValueNonConst.kt");
}
@TestMetadata("forInUntilLesserInt.kt") @TestMetadata("forInUntilLesserInt.kt")
public void testForInUntilLesserInt() throws Exception { public void testForInUntilLesserInt() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLesserInt.kt");
@@ -16422,19 +16462,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLong.kt");
} }
@TestMetadata("forInUntilMaxint.kt") @TestMetadata("forInUntilLongMaxValue.kt")
public void testForInUntilMaxint() throws Exception { public void testForInUntilLongMaxValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMaxint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMaxValue.kt");
} }
@TestMetadata("forInUntilMinint.kt") @TestMetadata("forInUntilLongMinValue.kt")
public void testForInUntilMinint() throws Exception { public void testForInUntilLongMinValue() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinint.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValue.kt");
} }
@TestMetadata("forInUntilMinlong.kt") @TestMetadata("forInUntilLongMinValueNonConst.kt")
public void testForInUntilMinlong() throws Exception { public void testForInUntilLongMinValueNonConst() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilMinlong.kt"); runTest("compiler/testData/codegen/box/ranges/forInUntil/forInUntilLongMinValueNonConst.kt");
} }
@TestMetadata("forIntInIntUntilSmartcastInt.kt") @TestMetadata("forIntInIntUntilSmartcastInt.kt")