KT-29229 Intrinsify 'in' operator for unsigned integer ranges
Support mixed type case, e.g., '[UByte] in [UIntRange]'.
This commit is contained in:
+11
-80
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-8
@@ -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
|
||||
|
||||
|
||||
+24
-2
@@ -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
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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)
|
||||
|
||||
+5
@@ -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)
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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)
|
||||
|
||||
+5
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user