diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt index 51418f7f258..5e9b657d5de 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/PrimitiveNumberRangeIntrinsicRangeValue.kt @@ -17,12 +17,11 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.UnsignedType -import org.jetbrains.kotlin.builtins.UnsignedTypes 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.getRangeContainsTypeInfo import org.jetbrains.kotlin.codegen.range.forLoop.ForInDefinitelySafeSimpleProgressionLoopGenerator import org.jetbrains.kotlin.codegen.range.forLoop.ForLoopGenerator import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator @@ -35,7 +34,6 @@ import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.constants.* -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.Type @@ -60,22 +58,20 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue( operatorReference: KtSimpleNameExpression, resolvedCall: ResolvedCall ): InExpressionGenerator { - val comparisonGenerator = getComparisonGeneratorForRangeContainsCall(codegen, resolvedCall) - val comparedType = comparisonGenerator?.comparedType + val rangeContainsTypeInfo = getRangeContainsTypeInfo(resolvedCall) + ?: return CallBasedInExpressionGenerator(codegen, operatorReference) + val comparisonGenerator = getComparisonGeneratorForRangeContainsCall(codegen, rangeContainsTypeInfo) + ?: return CallBasedInExpressionGenerator(codegen, operatorReference) - return when { - comparisonGenerator == null -> CallBasedInExpressionGenerator(codegen, operatorReference) - - comparedType == Type.DOUBLE_TYPE || comparedType == Type.FLOAT_TYPE -> { + return when (comparisonGenerator.comparedType) { + Type.DOUBLE_TYPE, Type.FLOAT_TYPE -> { val rangeLiteral = getBoundedValue(codegen) as? BoundedValue ?: throw AssertionError("Floating point intrinsic range value should be a range literal") InFloatingPointRangeLiteralExpressionGenerator(operatorReference, rangeLiteral, comparisonGenerator, codegen.frameMap) } - - else -> - InIntegralContinuousRangeExpressionGenerator( - operatorReference, getBoundedValue(codegen), comparisonGenerator, codegen.frameMap - ) + else -> InIntegralContinuousRangeExpressionGenerator( + operatorReference, rangeContainsTypeInfo, getBoundedValue(codegen), comparisonGenerator, codegen.frameMap + ) } } @@ -94,71 +90,6 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue( } } - private val StackValue.unsignedType: UnsignedType? - get() = kotlinType?.let { UnsignedTypes.toUnsignedType(it) } - - private fun coerceUnsignedToUInt(stackValue: StackValue, uIntKotlinType: KotlinType): StackValue { - val valueKotlinType = stackValue.kotlinType - val valueUnsignedType = stackValue.unsignedType - ?: throw AssertionError("Unsigned type expected: $valueKotlinType") - - if (valueUnsignedType == UnsignedType.UINT) return stackValue - - return StackValue.operation(Type.INT_TYPE, uIntKotlinType) { v -> - stackValue.put(stackValue.type, valueKotlinType, v) - when (valueUnsignedType) { - UnsignedType.UBYTE -> { - v.iconst(0xFF) - v.and(Type.INT_TYPE) - } - - UnsignedType.USHORT -> { - v.iconst(0xFFFF) - v.and(Type.INT_TYPE) - } - - UnsignedType.ULONG -> { - v.cast(Type.LONG_TYPE, Type.INT_TYPE) - } - - else -> throw AssertionError("Unexpected value type: $valueKotlinType") - } - } - } - - private fun coerceUnsignedToULong(stackValue: StackValue, uLongKotlinType: KotlinType): StackValue { - val valueKotlinType = stackValue.kotlinType - val valueUnsignedType = stackValue.unsignedType - ?: throw AssertionError("Unsigned type expected: $valueKotlinType") - - if (valueUnsignedType == UnsignedType.ULONG) return stackValue - - return StackValue.operation(Type.LONG_TYPE, uLongKotlinType) { v -> - stackValue.put(stackValue.type, valueKotlinType, v) - when (valueUnsignedType) { - UnsignedType.UBYTE -> { - v.cast(Type.INT_TYPE, Type.LONG_TYPE) - v.lconst(0xFF) - v.and(Type.LONG_TYPE) - } - - UnsignedType.USHORT -> { - v.cast(Type.INT_TYPE, Type.LONG_TYPE) - v.lconst(0xFFFF) - v.and(Type.LONG_TYPE) - } - - UnsignedType.UINT -> { - v.cast(Type.INT_TYPE, Type.LONG_TYPE) - v.lconst(0xFFFF_FFFFL) - v.and(Type.LONG_TYPE) - } - - else -> throw AssertionError("Unexpected value type: $valueKotlinType") - } - } - } - protected fun createConstBoundedForLoopGeneratorOrNull( codegen: ExpressionCodegen, forExpression: KtForExpression, @@ -251,7 +182,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue( ) private fun isProhibitedCharConstEndValue(step: Int, endValue: Char) = - endValue == if (step == 1) java.lang.Character.MAX_VALUE else java.lang.Character.MIN_VALUE + endValue == if (step == 1) Char.MAX_VALUE else Char.MIN_VALUE private fun isProhibitedIntConstEndValue(step: Int, endValue: Int) = endValue == if (step == 1) Int.MAX_VALUE else Int.MIN_VALUE diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeCodegenUtil.kt index f1ded0fbe73..0418b50b018 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeCodegenUtil.kt @@ -209,10 +209,12 @@ fun isPrimitiveRangeContains(descriptor: CallableDescriptor): Boolean { fun isUnsignedIntegerRangeContains(descriptor: CallableDescriptor): Boolean { if (descriptor.name.asString() != "contains") return false - val dispatchReceiverType = descriptor.dispatchReceiverParameter?.type ?: return false - if (!isUnsignedRange(dispatchReceiverType)) return false - return true + val dispatchReceiverType = descriptor.dispatchReceiverParameter?.type + val extensionReceiverType = descriptor.extensionReceiverParameter?.type + + return (dispatchReceiverType != null && isUnsignedRange(dispatchReceiverType)) || + (extensionReceiverType != null && isUnsignedRange(extensionReceiverType)) } fun isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(descriptor: CallableDescriptor): Boolean { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/UnsignedNumbersCoercion.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/UnsignedNumbersCoercion.kt new file mode 100644 index 00000000000..e1a5a6b9648 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/UnsignedNumbersCoercion.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.codegen.range + +import org.jetbrains.kotlin.builtins.UnsignedType +import org.jetbrains.kotlin.builtins.UnsignedTypes +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.org.objectweb.asm.Type + +val StackValue.unsignedType: UnsignedType? + get() = kotlinType?.let { UnsignedTypes.toUnsignedType(it) } + +fun coerceUnsignedToUInt(stackValue: StackValue, uIntKotlinType: KotlinType): StackValue = + coerceUnsignedToUInt(stackValue, stackValue.kotlinType, uIntKotlinType) + +fun coerceUnsignedToUInt( + stackValue: StackValue, + valueKotlinType: KotlinType?, + uIntKotlinType: KotlinType +): StackValue { + val valueUnsignedType = stackValue.unsignedType + ?: throw AssertionError("Unsigned type expected: $valueKotlinType") + + if (valueUnsignedType == UnsignedType.UINT) return stackValue + + return StackValue.operation(Type.INT_TYPE, uIntKotlinType) { v -> + stackValue.put(stackValue.type, valueKotlinType, v) + when (valueUnsignedType) { + UnsignedType.UBYTE -> { + v.iconst(0xFF) + v.and(Type.INT_TYPE) + } + + UnsignedType.USHORT -> { + v.iconst(0xFFFF) + v.and(Type.INT_TYPE) + } + + UnsignedType.ULONG -> { + v.cast(Type.LONG_TYPE, Type.INT_TYPE) + } + + else -> throw AssertionError("Unexpected value type: $valueKotlinType") + } + } +} + +fun coerceUnsignedToULong(stackValue: StackValue, uLongKotlinType: KotlinType): StackValue = + coerceUnsignedToULong(stackValue, stackValue.kotlinType, uLongKotlinType) + +fun coerceUnsignedToULong( + stackValue: StackValue, + valueKotlinType: KotlinType?, + uLongKotlinType: KotlinType +): StackValue { + val valueUnsignedType = stackValue.unsignedType + ?: throw AssertionError("Unsigned type expected: $valueKotlinType") + + if (valueUnsignedType == UnsignedType.ULONG) return stackValue + + return StackValue.operation(Type.LONG_TYPE, uLongKotlinType) { v -> + stackValue.put(stackValue.type, valueKotlinType, v) + when (valueUnsignedType) { + UnsignedType.UBYTE -> { + v.cast(Type.INT_TYPE, Type.LONG_TYPE) + v.lconst(0xFF) + v.and(Type.LONG_TYPE) + } + + UnsignedType.USHORT -> { + v.cast(Type.INT_TYPE, Type.LONG_TYPE) + v.lconst(0xFFFF) + v.and(Type.LONG_TYPE) + } + + UnsignedType.UINT -> { + v.cast(Type.INT_TYPE, Type.LONG_TYPE) + v.lconst(0xFFFF_FFFFL) + v.and(Type.LONG_TYPE) + } + + else -> throw AssertionError("Unexpected value type: $valueKotlinType") + } + } +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt index f87119417b6..ca4b68cb241 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/comparison/ComparisonGenerator.kt @@ -59,17 +59,25 @@ fun getComparisonGeneratorForKotlinType(kotlinType: KotlinType): ComparisonGener throw UnsupportedOperationException("Unexpected element type: $kotlinType") } +class RangeContainsTypeInfo( + val rangeElementType: KotlinType, + val valueParameterType: KotlinType +) + +fun getRangeContainsTypeInfo(call: ResolvedCall): RangeContainsTypeInfo? { + val descriptor = call.resultingDescriptor + val receiverType = descriptor.extensionReceiverParameter?.type ?: descriptor.dispatchReceiverParameter?.type ?: return null + val elementType = getRangeOrProgressionElementType(receiverType) ?: return null + val valueParameterType = descriptor.valueParameters.singleOrNull()?.type ?: return null + return RangeContainsTypeInfo(elementType, valueParameterType) +} + fun getComparisonGeneratorForRangeContainsCall( codegen: ExpressionCodegen, - call: ResolvedCall + rangeContainsTypeInfo: RangeContainsTypeInfo ): ComparisonGenerator? { - val descriptor = call.resultingDescriptor - - val receiverType = descriptor.extensionReceiverParameter?.type ?: descriptor.dispatchReceiverParameter?.type ?: return null - - val elementType = getRangeOrProgressionElementType(receiverType) ?: return null - - val valueParameterType = descriptor.valueParameters.singleOrNull()?.type ?: return null + val elementType = rangeContainsTypeInfo.rangeElementType + val valueParameterType = rangeContainsTypeInfo.valueParameterType val asmElementType = codegen.asmType(elementType) val asmValueParameterType = codegen.asmType(valueParameterType) @@ -78,6 +86,12 @@ fun getComparisonGeneratorForRangeContainsCall( asmElementType == asmValueParameterType -> getComparisonGeneratorForKotlinType(elementType) + KotlinBuiltIns.isUInt(elementType) -> + UIntComparisonGenerator + + KotlinBuiltIns.isULong(elementType) -> + ULongComparisonGenerator + asmElementType.isPrimitiveIntOrCoercible() && asmValueParameterType.isPrimitiveIntOrCoercible() -> IntComparisonGenerator diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InIntegralContinuousRangeExpressionGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InIntegralContinuousRangeExpressionGenerator.kt index d40d00928f7..d38745a7f1a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InIntegralContinuousRangeExpressionGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/inExpression/InIntegralContinuousRangeExpressionGenerator.kt @@ -16,9 +16,13 @@ package org.jetbrains.kotlin.codegen.range.inExpression +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.range.BoundedValue +import org.jetbrains.kotlin.codegen.range.coerceUnsignedToUInt +import org.jetbrains.kotlin.codegen.range.coerceUnsignedToULong import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator +import org.jetbrains.kotlin.codegen.range.comparison.RangeContainsTypeInfo import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.org.objectweb.asm.Label @@ -27,6 +31,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter class InIntegralContinuousRangeExpressionGenerator( operatorReference: KtSimpleNameExpression, + private val rangeContainsTypeInfo: RangeContainsTypeInfo, private val boundedValue: BoundedValue, private val comparisonGenerator: ComparisonGenerator, private val frameMap: FrameMap @@ -38,6 +43,7 @@ class InIntegralContinuousRangeExpressionGenerator( private fun gen(argument: StackValue): BranchedValue = object : BranchedValue(argument, null, comparisonGenerator.comparedType, Opcodes.IFEQ) { + override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) { if (jumpIfFalse) { genJumpIfFalse(v, jumpLabel) @@ -54,7 +60,7 @@ class InIntegralContinuousRangeExpressionGenerator( boundedValue.putHighLow(v, operandType) - arg1.put(operandType, v) + putCoercedArgumentOnStack(v) v.store(arg1Var, operandType) v.load(arg1Var, operandType) @@ -95,7 +101,7 @@ class InIntegralContinuousRangeExpressionGenerator( boundedValue.putHighLow(v, operandType) - arg1.put(operandType, v) + putCoercedArgumentOnStack(v) v.store(arg1Var, operandType) v.load(arg1Var, operandType) @@ -127,5 +133,21 @@ class InIntegralContinuousRangeExpressionGenerator( } } + + private fun putCoercedArgumentOnStack(v: InstructionAdapter) { + val argumentKotlinType = rangeContainsTypeInfo.valueParameterType + val rangeElementKotlinType = rangeContainsTypeInfo.rangeElementType + + val coercedValue = when { + KotlinBuiltIns.isUInt(rangeElementKotlinType) -> + coerceUnsignedToUInt(arg1, argumentKotlinType, rangeElementKotlinType) + KotlinBuiltIns.isULong(rangeElementKotlinType) -> + coerceUnsignedToULong(arg1, argumentKotlinType, rangeElementKotlinType) + else -> + arg1 + } + + coercedValue.put(operandType, v) + } } } \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt b/compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt new file mode 100644 index 00000000000..132819b96ae --- /dev/null +++ b/compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt @@ -0,0 +1,151 @@ +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME + +fun ub_ub(x: UByte, a: UByte, b: UByte) = x in a..b +fun ub_us(x: UByte, a: UShort, b: UShort) = x in a..b +fun ub_ui(x: UByte, a: UInt, b: UInt) = x in a..b +fun ub_ul(x: UByte, a: ULong, b: ULong) = x in a..b + +fun us_ub(x: UShort, a: UByte, b: UByte) = x in a..b +fun us_us(x: UShort, a: UShort, b: UShort) = x in a..b +fun us_ui(x: UShort, a: UInt, b: UInt) = x in a..b +fun us_ul(x: UShort, a: ULong, b: ULong) = x in a..b + +fun ui_ub(x: UInt, a: UByte, b: UByte) = x in a..b +fun ui_us(x: UInt, a: UShort, b: UShort) = x in a..b +fun ui_ui(x: UInt, a: UInt, b: UInt) = x in a..b +fun ui_ul(x: UInt, a: ULong, b: ULong) = x in a..b + +fun ul_ub(x: ULong, a: UByte, b: UByte) = x in a..b +fun ul_us(x: ULong, a: UShort, b: UShort) = x in a..b +fun ul_ui(x: ULong, a: UInt, b: UInt) = x in a..b +fun ul_ul(x: ULong, a: ULong, b: ULong) = x in a..b + +fun n_ub_ub(x: UByte, a: UByte, b: UByte) = x !in a..b +fun n_ub_us(x: UByte, a: UShort, b: UShort) = x !in a..b +fun n_ub_ui(x: UByte, a: UInt, b: UInt) = x !in a..b +fun n_ub_ul(x: UByte, a: ULong, b: ULong) = x !in a..b + +fun n_us_ub(x: UShort, a: UByte, b: UByte) = x !in a..b +fun n_us_us(x: UShort, a: UShort, b: UShort) = x !in a..b +fun n_us_ui(x: UShort, a: UInt, b: UInt) = x !in a..b +fun n_us_ul(x: UShort, a: ULong, b: ULong) = x !in a..b + +fun n_ui_ub(x: UInt, a: UByte, b: UByte) = x !in a..b +fun n_ui_us(x: UInt, a: UShort, b: UShort) = x !in a..b +fun n_ui_ui(x: UInt, a: UInt, b: UInt) = x !in a..b +fun n_ui_ul(x: UInt, a: ULong, b: ULong) = x !in a..b + +fun n_ul_ub(x: ULong, a: UByte, b: UByte) = x !in a..b +fun n_ul_us(x: ULong, a: UShort, b: UShort) = x !in a..b +fun n_ul_ui(x: ULong, a: UInt, b: UInt) = x !in a..b +fun n_ul_ul(x: ULong, a: ULong, b: ULong) = x !in a..b + +fun box(): String { + + // 'in' tests + + if (!ub_ub(1.toUByte(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (!ub_ub(200.toUByte(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (!ub_us(1.toUByte(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (!ub_us(200.toUByte(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (!ub_ui(1.toUByte(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (!ub_ui(200.toUByte(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (!ub_ul(1.toUByte(), 0.toULong(), 2.toULong())) throw AssertionError() + if (!ub_ul(200.toUByte(), 10.toULong(), 255.toULong())) throw AssertionError() + + if (!us_ub(1.toUShort(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (!us_ub(200.toUShort(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (!us_us(1.toUShort(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (!us_us(200.toUShort(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (!us_us(60000.toUShort(), 10000.toUShort(), 65000.toUShort())) throw AssertionError() + if (!us_ui(1.toUShort(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (!us_ui(200.toUShort(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (!us_ui(60000.toUShort(), 10000.toUInt(), 65000.toUInt())) throw AssertionError() + if (!us_ul(1.toUShort(), 0.toULong(), 2.toULong())) throw AssertionError() + if (!us_ul(200.toUShort(), 10.toULong(), 255.toULong())) throw AssertionError() + if (!us_ul(60000.toUShort(), 10000.toULong(), 65000.toULong())) throw AssertionError() + + if (!ui_ub(1.toUInt(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (!ui_ub(200.toUInt(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (!ui_us(1.toUInt(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (!ui_us(200.toUInt(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (!ui_us(60000.toUInt(), 10000.toUShort(), 65000.toUShort())) throw AssertionError() + if (!ui_ui(1.toUInt(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (!ui_ui(200.toUInt(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (!ui_ui(60000.toUInt(), 10000.toUInt(), 65000.toUInt())) throw AssertionError() + if (!ui_ui(2200000000L.toUInt(), 2000000000L.toUInt(), 2400000000L.toUInt())) throw AssertionError() + if (!ui_ul(1.toUInt(), 0.toULong(), 2.toULong())) throw AssertionError() + if (!ui_ul(200.toUInt(), 10.toULong(), 255.toULong())) throw AssertionError() + if (!ui_ul(60000.toUInt(), 10000.toULong(), 65000.toULong())) throw AssertionError() + if (!ui_ul(2200000000L.toUInt(), 2000000000L.toULong(), 2400000000L.toULong())) throw AssertionError() + + if (!ul_ub(1.toULong(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (!ul_ub(200.toULong(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (!ul_us(1.toULong(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (!ul_us(200.toULong(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (!ul_us(60000.toULong(), 10000.toUShort(), 65000.toUShort())) throw AssertionError() + if (!ul_ui(1.toULong(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (!ul_ui(200.toULong(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (!ul_ui(60000.toULong(), 10000.toUInt(), 65000.toUInt())) throw AssertionError() + if (!ul_ui(2200000000L.toULong(), 2000000000L.toUInt(), 2400000000L.toUInt())) throw AssertionError() + if (!ul_ul(1.toULong(), 0.toULong(), 2.toULong())) throw AssertionError() + if (!ul_ul(200.toULong(), 10.toULong(), 255.toULong())) throw AssertionError() + if (!ul_ul(60000.toULong(), 10000.toULong(), 65000.toULong())) throw AssertionError() + if (!ul_ul(2200000000L.toULong(), 2000000000L.toULong(), 2400000000L.toULong())) throw AssertionError() + if (!ul_ul(ULong.MAX_VALUE - 10.toULong(), UInt.MAX_VALUE.toULong(), ULong.MAX_VALUE - 1.toULong())) throw AssertionError() + + // '!in' tests + + if (n_ub_ub(1.toUByte(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (n_ub_ub(200.toUByte(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (n_ub_us(1.toUByte(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (n_ub_us(200.toUByte(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (n_ub_ui(1.toUByte(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (n_ub_ui(200.toUByte(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (n_ub_ul(1.toUByte(), 0.toULong(), 2.toULong())) throw AssertionError() + if (n_ub_ul(200.toUByte(), 10.toULong(), 255.toULong())) throw AssertionError() + + if (n_us_ub(1.toUShort(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (n_us_ub(200.toUShort(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (n_us_us(1.toUShort(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (n_us_us(200.toUShort(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (n_us_us(60000.toUShort(), 10000.toUShort(), 65000.toUShort())) throw AssertionError() + if (n_us_ui(1.toUShort(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (n_us_ui(200.toUShort(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (n_us_ui(60000.toUShort(), 10000.toUInt(), 65000.toUInt())) throw AssertionError() + if (n_us_ul(1.toUShort(), 0.toULong(), 2.toULong())) throw AssertionError() + if (n_us_ul(200.toUShort(), 10.toULong(), 255.toULong())) throw AssertionError() + if (n_us_ul(60000.toUShort(), 10000.toULong(), 65000.toULong())) throw AssertionError() + + if (n_ui_ub(1.toUInt(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (n_ui_ub(200.toUInt(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (n_ui_us(1.toUInt(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (n_ui_us(200.toUInt(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (n_ui_us(60000.toUInt(), 10000.toUShort(), 65000.toUShort())) throw AssertionError() + if (n_ui_ui(1.toUInt(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (n_ui_ui(200.toUInt(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (n_ui_ui(60000.toUInt(), 10000.toUInt(), 65000.toUInt())) throw AssertionError() + if (n_ui_ui(2200000000L.toUInt(), 2000000000L.toUInt(), 2400000000L.toUInt())) throw AssertionError() + if (n_ui_ul(1.toUInt(), 0.toULong(), 2.toULong())) throw AssertionError() + if (n_ui_ul(200.toUInt(), 10.toULong(), 255.toULong())) throw AssertionError() + if (n_ui_ul(60000.toUInt(), 10000.toULong(), 65000.toULong())) throw AssertionError() + if (n_ui_ul(2200000000L.toUInt(), 2000000000L.toULong(), 2400000000L.toULong())) throw AssertionError() + + if (n_ul_ub(1.toULong(), 0.toUByte(), 2.toUByte())) throw AssertionError() + if (n_ul_ub(200.toULong(), 10.toUByte(), 255.toUByte())) throw AssertionError() + if (n_ul_us(1.toULong(), 0.toUShort(), 2.toUShort())) throw AssertionError() + if (n_ul_us(200.toULong(), 10.toUShort(), 255.toUShort())) throw AssertionError() + if (n_ul_us(60000.toULong(), 10000.toUShort(), 65000.toUShort())) throw AssertionError() + if (n_ul_ui(1.toULong(), 0.toUInt(), 2.toUInt())) throw AssertionError() + if (n_ul_ui(200.toULong(), 10.toUInt(), 255.toUInt())) throw AssertionError() + if (n_ul_ui(60000.toULong(), 10000.toUInt(), 65000.toUInt())) throw AssertionError() + if (n_ul_ui(2200000000L.toULong(), 2000000000L.toUInt(), 2400000000L.toUInt())) throw AssertionError() + if (n_ul_ul(1.toULong(), 0.toULong(), 2.toULong())) throw AssertionError() + if (n_ul_ul(200.toULong(), 10.toULong(), 255.toULong())) throw AssertionError() + if (n_ul_ul(60000.toULong(), 10000.toULong(), 65000.toULong())) throw AssertionError() + if (n_ul_ul(2200000000L.toULong(), 2000000000L.toULong(), 2400000000L.toULong())) throw AssertionError() + if (n_ul_ul(ULong.MAX_VALUE - 10.toULong(), UInt.MAX_VALUE.toULong(), ULong.MAX_VALUE - 1.toULong())) throw AssertionError() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/ranges/inMixedUnsignedRange.kt b/compiler/testData/codegen/bytecodeText/ranges/inMixedUnsignedRange.kt new file mode 100644 index 00000000000..3093a95ac74 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/ranges/inMixedUnsignedRange.kt @@ -0,0 +1,51 @@ +// IGNORE_BACKEND: JVM_IR + +fun ub_ub(x: UByte, a: UByte, b: UByte) = x in a..b +fun ub_us(x: UByte, a: UShort, b: UShort) = x in a..b +fun ub_ui(x: UByte, a: UInt, b: UInt) = x in a..b +fun ub_ul(x: UByte, a: ULong, b: ULong) = x in a..b + +fun us_ub(x: UShort, a: UByte, b: UByte) = x in a..b +fun us_us(x: UShort, a: UShort, b: UShort) = x in a..b +fun us_ui(x: UShort, a: UInt, b: UInt) = x in a..b +fun us_ul(x: UShort, a: ULong, b: ULong) = x in a..b + +fun ui_ub(x: UInt, a: UByte, b: UByte) = x in a..b +fun ui_us(x: UInt, a: UShort, b: UShort) = x in a..b +fun ui_ui(x: UInt, a: UInt, b: UInt) = x in a..b +fun ui_ul(x: UInt, a: ULong, b: ULong) = x in a..b + +fun ul_ub(x: ULong, a: UByte, b: UByte) = x in a..b +fun ul_us(x: ULong, a: UShort, b: UShort) = x in a..b +fun ul_ui(x: ULong, a: UInt, b: UInt) = x in a..b +fun ul_ul(x: ULong, a: ULong, b: ULong) = x in a..b + +fun n_ub_ub(x: UByte, a: UByte, b: UByte) = x !in a..b +fun n_ub_us(x: UByte, a: UShort, b: UShort) = x !in a..b +fun n_ub_ui(x: UByte, a: UInt, b: UInt) = x !in a..b +fun n_ub_ul(x: UByte, a: ULong, b: ULong) = x !in a..b + +fun n_us_ub(x: UShort, a: UByte, b: UByte) = x !in a..b +fun n_us_us(x: UShort, a: UShort, b: UShort) = x !in a..b +fun n_us_ui(x: UShort, a: UInt, b: UInt) = x !in a..b +fun n_us_ul(x: UShort, a: ULong, b: ULong) = x !in a..b + +fun n_ui_ub(x: UInt, a: UByte, b: UByte) = x !in a..b +fun n_ui_us(x: UInt, a: UShort, b: UShort) = x !in a..b +fun n_ui_ui(x: UInt, a: UInt, b: UInt) = x !in a..b +fun n_ui_ul(x: UInt, a: ULong, b: ULong) = x !in a..b + +fun n_ul_ub(x: ULong, a: UByte, b: UByte) = x !in a..b +fun n_ul_us(x: ULong, a: UShort, b: UShort) = x !in a..b +fun n_ul_ui(x: ULong, a: UInt, b: UInt) = x !in a..b +fun n_ul_ul(x: ULong, a: ULong, b: ULong) = x !in a..b + +// 0 contains +// 16 IFLE +// 16 IFLT +// 16 IFGE +// 16 IFGT +// 6 L2I +// 22 SIPUSH 255 +// 24 LDC 65535 +// 2 LDC 4294967295 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 56d3ed6ec35..a9e920e2c15 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -19839,6 +19839,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("inMixedUnsignedRange.kt") + public void testInMixedUnsignedRange() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt"); + } + @TestMetadata("compiler/testData/codegen/box/ranges/unsigned/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 579dfc33c35..38b8c4ab57b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3448,6 +3448,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/ranges/inComparableRangeLiteral.kt"); } + @TestMetadata("inMixedUnsignedRange.kt") + public void testInMixedUnsignedRange() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/ranges/inMixedUnsignedRange.kt"); + } + @TestMetadata("inNonMatchingRangeIntrinsified.kt") public void testInNonMatchingRangeIntrinsified() throws Exception { runTest("compiler/testData/codegen/bytecodeText/ranges/inNonMatchingRangeIntrinsified.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index c40117ddd93..6684404c5ab 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -19839,6 +19839,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("inMixedUnsignedRange.kt") + public void testInMixedUnsignedRange() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt"); + } + @TestMetadata("compiler/testData/codegen/box/ranges/unsigned/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index fd8cdf33ebd..aed78206b06 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -18724,6 +18724,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("inMixedUnsignedRange.kt") + public void testInMixedUnsignedRange() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt"); + } + @TestMetadata("compiler/testData/codegen/box/ranges/unsigned/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index dd512f6a895..1f78337ed46 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3418,6 +3418,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/ranges/inComparableRangeLiteral.kt"); } + @TestMetadata("inMixedUnsignedRange.kt") + public void testInMixedUnsignedRange() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/ranges/inMixedUnsignedRange.kt"); + } + @TestMetadata("inNonMatchingRangeIntrinsified.kt") public void testInNonMatchingRangeIntrinsified() throws Exception { runTest("compiler/testData/codegen/bytecodeText/ranges/inNonMatchingRangeIntrinsified.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 0203ce54133..5c13f571438 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -15674,6 +15674,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); } + @TestMetadata("inMixedUnsignedRange.kt") + public void testInMixedUnsignedRange() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt"); + } + @TestMetadata("compiler/testData/codegen/box/ranges/unsigned/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 58810600576..4628998f68a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -16829,6 +16829,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); } + @TestMetadata("inMixedUnsignedRange.kt") + public void testInMixedUnsignedRange() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt"); + } + @TestMetadata("compiler/testData/codegen/box/ranges/unsigned/expression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)