KT-29229 Intrinsify 'in' operator for unsigned integer ranges

Support mixed type case, e.g., '[UByte] in [UIntRange]'.
This commit is contained in:
Dmitry Petrov
2019-05-29 17:12:01 +03:00
parent 5426071102
commit 0531bd4fe6
14 changed files with 388 additions and 93 deletions
@@ -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<out CallableDescriptor>
): 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
@@ -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 {
@@ -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")
}
}
}
@@ -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<out CallableDescriptor>): 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<out CallableDescriptor>
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
@@ -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)
}
}
}
@@ -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"
}
@@ -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
@@ -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)
@@ -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");
@@ -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)
@@ -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)
@@ -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");
@@ -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)
@@ -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)