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