Use ComparisonGenerator for range element type in counter loops

This commit is contained in:
Dmitry Petrov
2018-12-26 16:16:10 +03:00
parent 4e48ce02f1
commit 5ae8df4d88
15 changed files with 147 additions and 100 deletions
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.range.comparison.IntComparisonGenerator
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInDefinitelySafeSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
@@ -36,7 +38,7 @@ class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen.asmType(rangeCall.resultingDescriptor.returnType!!),
StackValue.constant(0, asmElementType),
StackValue.constant(0, elementType),
true,
StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), expectedReceiverType, v)
@@ -46,10 +48,12 @@ class ArrayIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor>) :
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
codegen, forExpression, getBoundedValue(codegen), IntComparisonGenerator
)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
codegen, forExpression, getBoundedValue(codegen), IntComparisonGenerator
)
}
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.range.comparison.IntComparisonGenerator
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInDefinitelySafeSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -35,7 +37,7 @@ class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescript
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen.asmType(rangeCall.resultingDescriptor.returnType!!),
StackValue.constant(0, asmElementType),
StackValue.constant(0, elementType),
true,
StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), expectedReceiverType, v)
@@ -45,10 +47,12 @@ class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescript
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
codegen, forExpression, getBoundedValue(codegen), IntComparisonGenerator
)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
codegen, forExpression, getBoundedValue(codegen), IntComparisonGenerator
)
}
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.range.comparison.IntComparisonGenerator
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInDefinitelySafeSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -35,7 +37,7 @@ class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor
override fun getBoundedValue(codegen: ExpressionCodegen) =
SimpleBoundedValue(
codegen.asmType(rangeCall.resultingDescriptor.returnType!!),
StackValue.constant(0, asmElementType),
StackValue.constant(0, elementType),
true,
StackValue.operation(Type.INT_TYPE) { v ->
codegen.generateCallReceiver(rangeCall).put(codegen.asmType(expectedReceiverType), expectedReceiverType, v)
@@ -45,10 +47,12 @@ class CollectionIndicesRangeValue(rangeCall: ResolvedCall<out CallableDescriptor
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
codegen, forExpression, getBoundedValue(codegen), IntComparisonGenerator
)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInDefinitelySafeSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen)
codegen, forExpression, getBoundedValue(codegen), IntComparisonGenerator
)
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.generateCallSingleArgument
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -39,12 +40,16 @@ class DownToProgressionRangeValue(rangeCall: ResolvedCall<out CallableDescriptor
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
createConstBoundedForInDownToGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(codegen, forExpression, getBoundedValue(codegen))
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen),
getComparisonGeneratorForKotlinType(elementKotlinType)
)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
createConstBoundedForInReversedDownToGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
codegen, forExpression, getBoundedValue(codegen),
getComparisonGeneratorForKotlinType(elementKotlinType),
inverseBoundsEvaluationOrder = true
)
@@ -16,7 +16,9 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
import org.jetbrains.kotlin.codegen.range.forLoop.ForInDefinitelySafeSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
@@ -36,7 +38,12 @@ import org.jetbrains.org.objectweb.asm.Type
abstract class PrimitiveNumberRangeIntrinsicRangeValue(
rangeCall: ResolvedCall<out CallableDescriptor>
) : CallIntrinsicRangeValue(rangeCall) {
protected val asmElementType = getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCall.resultingDescriptor)
protected val elementKotlinType =
rangeCall.resultingDescriptor.returnType?.let { getRangeOrProgressionElementType(it) }
?: throw AssertionError("Unexpected range ")
protected val elementType = getAsmRangeElementTypeForPrimitiveRangeOrProgression(rangeCall.resultingDescriptor)
override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall<out CallableDescriptor>) =
resolvedCallForIn.resultingDescriptor.let {
@@ -138,8 +145,9 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
codegen, forExpression,
startValue = startValue,
isStartInclusive = isStartInclusive,
endValue = StackValue.integerConstant(endIntValue, asmElementType),
endValue = StackValue.integerConstant(endIntValue, elementType),
isEndInclusive = true,
comparisonGenerator = getComparisonGeneratorForKotlinType(elementKotlinType),
step = step
)
@@ -155,8 +163,9 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(
codegen, forExpression,
startValue = startValue,
isStartInclusive = isStartInclusive,
endValue = StackValue.constant(endLongValue, asmElementType),
endValue = StackValue.constant(endLongValue, elementType),
isEndInclusive = true,
comparisonGenerator = getComparisonGeneratorForKotlinType(elementKotlinType),
step = step
)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.generateCallSingleArgument
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -51,12 +52,16 @@ class PrimitiveNumberRangeLiteralRangeValue(
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
createConstBoundedForInRangeLiteralGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
codegen, forExpression, getBoundedValue(codegen),
getComparisonGeneratorForKotlinType(elementKotlinType)
)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
createConstBoundedRangeForInReversedRangeLiteralGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen),
getComparisonGeneratorForKotlinType(elementKotlinType),
inverseBoundsEvaluationOrder = true
)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.generateCallReceiver
import org.jetbrains.kotlin.codegen.generateCallSingleArgument
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInSimpleProgressionLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.descriptors.CallableDescriptor
@@ -39,12 +40,16 @@ class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall<out CallableDescrip
)
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(codegen, forExpression, getBoundedValue(codegen))
ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStep1(
codegen, forExpression, getBoundedValue(codegen),
getComparisonGeneratorForKotlinType(elementKotlinType)
)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
createConstBoundedForInReversedUntilGenerator(codegen, forExpression)
?: ForInSimpleProgressionLoopGenerator.fromBoundedValueWithStepMinus1(
codegen, forExpression, getBoundedValue(codegen),
getComparisonGeneratorForKotlinType(elementKotlinType),
inverseBoundsEvaluationOrder = true
)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.range
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForKotlinType
import org.jetbrains.kotlin.codegen.range.forLoop.ForInRangeInstanceLoopGenerator
import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
@@ -24,15 +25,33 @@ import org.jetbrains.kotlin.codegen.range.inExpression.InExpressionGenerator
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.types.KotlinType
class PrimitiveRangeRangeValue(private val rangeExpression: KtExpression) : ReversableRangeValue {
override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) =
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = false)
ForInRangeInstanceLoopGenerator(
codegen, forExpression, rangeExpression,
getComparisonGeneratorForKotlinType(getRangeElementType(codegen, forExpression)),
reversed = false
)
override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator =
CallBasedInExpressionGenerator(codegen, operatorReference)
override fun createForInReversedLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression): ForLoopGenerator =
ForInRangeInstanceLoopGenerator(codegen, forExpression, rangeExpression, reversed = true)
ForInRangeInstanceLoopGenerator(
codegen, forExpression, rangeExpression,
getComparisonGeneratorForKotlinType(getRangeElementType(codegen, forExpression)),
reversed = true
)
private fun getRangeElementType(codegen: ExpressionCodegen, forExpression: KtForExpression): KotlinType {
val ktLoopRange = forExpression.loopRange
?: throw AssertionError("No loop range expression: ${forExpression.text}")
val rangeType = codegen.bindingContext.getType(ktLoopRange)
?: throw AssertionError("No type for loop range expression: ${ktLoopRange.text}")
return getRangeOrProgressionElementType(rangeType)
?: throw AssertionError("Unexpected range type: $rangeType")
}
}
@@ -16,10 +16,12 @@
package org.jetbrains.kotlin.codegen.range.comparison
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.getRangeOrProgressionElementType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -33,14 +35,20 @@ interface ComparisonGenerator {
fun jumpIfLess(v: InstructionAdapter, label: Label)
}
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
fun getComparisonGeneratorForKotlinType(kotlinType: KotlinType): ComparisonGenerator =
when {
type == Type.CHAR_TYPE -> CharComparisonGenerator
type.isPrimitiveIntOrCoercible() -> IntComparisonGenerator
type == Type.LONG_TYPE -> LongComparisonGenerator
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
else -> throw UnsupportedOperationException("Unexpected primitive type: " + type)
KotlinBuiltIns.isChar(kotlinType) ->
CharComparisonGenerator
KotlinBuiltIns.isByte(kotlinType) || KotlinBuiltIns.isShort(kotlinType) || KotlinBuiltIns.isInt(kotlinType) ->
IntComparisonGenerator
KotlinBuiltIns.isLong(kotlinType) ->
LongComparisonGenerator
KotlinBuiltIns.isFloat(kotlinType) ->
FloatComparisonGenerator
KotlinBuiltIns.isDouble(kotlinType) ->
DoubleComparisonGenerator
else ->
throw UnsupportedOperationException("Unexpected element type: $kotlinType")
}
fun getComparisonGeneratorForRangeContainsCall(
@@ -60,7 +68,7 @@ fun getComparisonGeneratorForRangeContainsCall(
return when {
asmElementType == asmValueParameterType ->
getComparisonGeneratorForPrimitiveType(asmElementType)
getComparisonGeneratorForKotlinType(elementType)
asmElementType.isPrimitiveIntOrCoercible() && asmValueParameterType.isPrimitiveIntOrCoercible() ->
IntComparisonGenerator
@@ -20,7 +20,7 @@ import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
sealed class FloatingPointComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
class FloatingPointComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
v.cmpg(comparedType)
v.ifge(label)
@@ -42,6 +42,5 @@ sealed class FloatingPointComparisonGenerator(override val comparedType: Type) :
}
}
object FloatComparisonGenerator : FloatingPointComparisonGenerator(Type.FLOAT_TYPE)
object DoubleComparisonGenerator : FloatingPointComparisonGenerator(Type.DOUBLE_TYPE)
val FloatComparisonGenerator = FloatingPointComparisonGenerator(Type.FLOAT_TYPE)
val DoubleComparisonGenerator = FloatingPointComparisonGenerator(Type.DOUBLE_TYPE)
@@ -20,7 +20,7 @@ import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
abstract class IntegerComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
class IntegerComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
v.ificmpge(label)
}
@@ -38,6 +38,5 @@ abstract class IntegerComparisonGenerator(override val comparedType: Type) : Com
}
}
object IntComparisonGenerator : IntegerComparisonGenerator(Type.INT_TYPE)
object CharComparisonGenerator : IntegerComparisonGenerator(Type.CHAR_TYPE)
val IntComparisonGenerator = IntegerComparisonGenerator(Type.INT_TYPE)
val CharComparisonGenerator = IntegerComparisonGenerator(Type.CHAR_TYPE)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
@@ -26,7 +27,8 @@ import org.jetbrains.org.objectweb.asm.Type
abstract class AbstractForInRangeLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
protected val step: Int
protected val step: Int,
protected val comparisonGenerator: ComparisonGenerator
) : AbstractForInProgressionOrRangeLoopGenerator(codegen, forExpression) {
override fun beforeLoop() {
@@ -40,19 +42,11 @@ abstract class AbstractForInRangeLoopGenerator(
override fun checkEmptyLoop(loopExit: Label) {
loopParameter().put(asmElementType, elementType, v)
v.load(endVar, asmElementType)
if (asmElementType.sort == Type.LONG) {
v.lcmp()
if (step > 0) {
v.ifgt(loopExit)
} else {
v.iflt(loopExit)
}
if (step > 0) {
comparisonGenerator.jumpIfGreater(v, loopExit)
} else {
if (step > 0) {
v.ificmpgt(loopExit)
} else {
v.ificmplt(loopExit)
}
comparisonGenerator.jumpIfLess(v, loopExit)
}
}
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.range.SimpleBoundedValue
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
/**
* Generates "naive" for loop:
@@ -45,13 +45,15 @@ class ForInDefinitelySafeSimpleProgressionLoopGenerator(
private val isStartInclusive: Boolean,
private val endValue: StackValue,
private val isEndInclusive: Boolean,
comparisonGenerator: ComparisonGenerator,
step: Int
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step) {
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step, comparisonGenerator) {
constructor(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
comparisonGenerator: ComparisonGenerator,
step: Int
) : this(
codegen, forExpression,
@@ -59,15 +61,26 @@ class ForInDefinitelySafeSimpleProgressionLoopGenerator(
isStartInclusive = if (step == 1) boundedValue.isLowInclusive else boundedValue.isHighInclusive,
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
comparisonGenerator = comparisonGenerator,
step = step
)
companion object {
fun fromBoundedValueWithStep1(codegen: ExpressionCodegen, forExpression: KtForExpression, boundedValue: SimpleBoundedValue) =
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, 1)
fun fromBoundedValueWithStep1(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
comparisonGenerator: ComparisonGenerator
) =
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, comparisonGenerator, 1)
fun fromBoundedValueWithStepMinus1(codegen: ExpressionCodegen, forExpression: KtForExpression, boundedValue: SimpleBoundedValue) =
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, -1)
fun fromBoundedValueWithStepMinus1(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
comparisonGenerator: ComparisonGenerator
) =
ForInDefinitelySafeSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, comparisonGenerator, -1)
}
override fun storeRangeStartAndEnd() {
@@ -84,35 +97,17 @@ class ForInDefinitelySafeSimpleProgressionLoopGenerator(
override fun checkPreCondition(loopExit: Label) {
loopParameter().put(asmElementType, elementType, v)
v.load(endVar, asmElementType)
if (asmElementType.sort == Type.LONG) {
v.lcmp()
if (step > 0) {
if (isEndInclusive) {
v.ifgt(loopExit)
} else {
v.ifge(loopExit)
}
} else {
if (isEndInclusive) {
v.iflt(loopExit)
} else {
v.ifle(loopExit)
}
}
if (step > 0) {
if (isEndInclusive)
comparisonGenerator.jumpIfGreater(v, loopExit)
else
comparisonGenerator.jumpIfGreaterOrEqual(v, loopExit)
} else {
if (step > 0) {
if (isEndInclusive) {
v.ificmpgt(loopExit)
} else {
v.ificmpge(loopExit)
}
} else {
if (isEndInclusive) {
v.ificmplt(loopExit)
} else {
v.ificmple(loopExit)
}
}
if (isEndInclusive)
comparisonGenerator.jumpIfLess(v, loopExit)
else
comparisonGenerator.jumpIfLessOrEqual(v, loopExit)
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtForExpression
@@ -24,8 +25,9 @@ class ForInRangeInstanceLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
private val rangeExpression: KtExpression,
comparisonGenerator: ComparisonGenerator,
private val reversed: Boolean
) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1) {
) : AbstractForInRangeLoopGenerator(codegen, forExpression, if (reversed) -1 else 1, comparisonGenerator) {
override fun storeRangeStartAndEnd() {
val loopRangeType = codegen.bindingContext.getType(rangeExpression)!!
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.codegen.range.forLoop
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.range.SimpleBoundedValue
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
class ForInSimpleProgressionLoopGenerator(
codegen: ExpressionCodegen,
@@ -31,14 +31,16 @@ class ForInSimpleProgressionLoopGenerator(
private val endValue: StackValue,
private val isEndInclusive: Boolean,
private val inverseBoundsEvaluationOrder: Boolean,
comparisonGenerator: ComparisonGenerator,
step: Int
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step) {
) : AbstractForInRangeLoopGenerator(codegen, forExpression, step, comparisonGenerator) {
constructor(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
inverseBoundsEvaluationOrder: Boolean,
comparisonGenerator: ComparisonGenerator,
step: Int
) : this(
codegen, forExpression,
@@ -47,6 +49,7 @@ class ForInSimpleProgressionLoopGenerator(
endValue = if (step == 1) boundedValue.highBound else boundedValue.lowBound,
isEndInclusive = if (step == 1) boundedValue.isHighInclusive else boundedValue.isLowInclusive,
inverseBoundsEvaluationOrder = inverseBoundsEvaluationOrder,
comparisonGenerator = comparisonGenerator,
step = step
)
@@ -55,17 +58,19 @@ class ForInSimpleProgressionLoopGenerator(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
comparisonGenerator: ComparisonGenerator,
inverseBoundsEvaluationOrder: Boolean = false
) =
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, 1)
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, comparisonGenerator, 1)
fun fromBoundedValueWithStepMinus1(
codegen: ExpressionCodegen,
forExpression: KtForExpression,
boundedValue: SimpleBoundedValue,
comparisonGenerator: ComparisonGenerator,
inverseBoundsEvaluationOrder: Boolean = false
) =
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, -1)
ForInSimpleProgressionLoopGenerator(codegen, forExpression, boundedValue, inverseBoundsEvaluationOrder, comparisonGenerator, -1)
}
override fun storeRangeStartAndEnd() {
@@ -93,20 +98,10 @@ class ForInSimpleProgressionLoopGenerator(
if (!isEndInclusive) {
loopParameter().put(asmElementType, elementType, v)
v.load(endVar, asmElementType)
if (asmElementType.sort == Type.LONG) {
v.lcmp()
if (step > 0) {
v.ifge(loopExit)
} else {
v.ifle(loopExit)
}
} else {
if (step > 0) {
v.ificmpge(loopExit)
} else {
v.ificmple(loopExit)
}
}
if (step > 0)
comparisonGenerator.jumpIfGreaterOrEqual(v, loopExit)
else
comparisonGenerator.jumpIfLessOrEqual(v, loopExit)
}
}