From 62fb47d1371825ed8f72cf9da41940f52eeff4ba Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Wed, 28 Sep 2016 06:57:17 +0300 Subject: [PATCH] Introduce bitwise operations and/or/xor/inv for Byte and Short. #KT-13554 Annotate new bitwise operations with SinceKotlin. --- .../builtin-classes/default/kotlin.txt | 8 +++ .../testData/builtin-classes/java6/kotlin.txt | 8 +++ .../testData/builtin-classes/java8/kotlin.txt | 8 +++ .../builtin-classes/newMethods/kotlin.txt | 8 +++ .../codegen/box/binaryOp/bitwiseOp.kt | 67 +++++++++++++++++++ .../codegen/box/binaryOp/bitwiseOpAny.kt | 67 +++++++++++++++++++ .../codegen/box/binaryOp/bitwiseOpNullable.kt | 67 +++++++++++++++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 18 +++++ .../codegen/BlackBoxCodegenTestGenerated.java | 18 +++++ core/builtins/native/kotlin/Primitives.kt | 26 +++++++ .../kotlin/generators/builtins/primitives.kt | 11 ++- 11 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/binaryOp/bitwiseOp.kt create mode 100644 compiler/testData/codegen/box/binaryOp/bitwiseOpAny.kt create mode 100644 compiler/testData/codegen/box/binaryOp/bitwiseOpNullable.kt diff --git a/compiler/testData/builtin-classes/default/kotlin.txt b/compiler/testData/builtin-classes/default/kotlin.txt index 6897bf0788f..025c5182aea 100644 --- a/compiler/testData/builtin-classes/default/kotlin.txt +++ b/compiler/testData/builtin-classes/default/kotlin.txt @@ -51,6 +51,7 @@ public final class BooleanArray { public final class Byte : kotlin.Number, kotlin.Comparable { /*primary*/ private constructor Byte() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Byte): kotlin.Byte public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -65,6 +66,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable { public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Byte + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Byte public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -77,6 +79,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable { public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Byte): kotlin.Byte public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -102,6 +105,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable { public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Byte): kotlin.Byte public companion object Companion { /*primary*/ private constructor Companion() @@ -569,6 +573,7 @@ public abstract class Number { public final class Short : kotlin.Number, kotlin.Comparable { /*primary*/ private constructor Short() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -583,6 +588,7 @@ public final class Short : kotlin.Number, kotlin.Comparable { public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Short + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Short public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -595,6 +601,7 @@ public final class Short : kotlin.Number, kotlin.Comparable { public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -620,6 +627,7 @@ public final class Short : kotlin.Number, kotlin.Comparable { public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Short): kotlin.Short public companion object Companion { /*primary*/ private constructor Companion() diff --git a/compiler/testData/builtin-classes/java6/kotlin.txt b/compiler/testData/builtin-classes/java6/kotlin.txt index 2e9bc8b559e..8ef1e79822a 100644 --- a/compiler/testData/builtin-classes/java6/kotlin.txt +++ b/compiler/testData/builtin-classes/java6/kotlin.txt @@ -53,6 +53,7 @@ public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializ public final class Byte : kotlin.Number, kotlin.Comparable, java.io.Serializable { /*primary*/ private constructor Byte() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Byte): kotlin.Byte public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -67,6 +68,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Byte + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Byte public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -79,6 +81,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Byte): kotlin.Byte public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -104,6 +107,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Byte): kotlin.Byte public companion object Companion { /*primary*/ private constructor Companion() @@ -585,6 +589,7 @@ public abstract class Number : kotlin.Any, java.io.Serializable { public final class Short : kotlin.Number, kotlin.Comparable, java.io.Serializable { /*primary*/ private constructor Short() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -599,6 +604,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Short + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Short public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -611,6 +617,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -636,6 +643,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Short): kotlin.Short public companion object Companion { /*primary*/ private constructor Companion() diff --git a/compiler/testData/builtin-classes/java8/kotlin.txt b/compiler/testData/builtin-classes/java8/kotlin.txt index f019d7a0d39..ebdd6d3ab23 100644 --- a/compiler/testData/builtin-classes/java8/kotlin.txt +++ b/compiler/testData/builtin-classes/java8/kotlin.txt @@ -53,6 +53,7 @@ public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializ public final class Byte : kotlin.Number, kotlin.Comparable, java.io.Serializable { /*primary*/ private constructor Byte() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Byte): kotlin.Byte public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -67,6 +68,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Byte + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Byte public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -79,6 +81,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Byte): kotlin.Byte public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -104,6 +107,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Byte): kotlin.Byte public companion object Companion { /*primary*/ private constructor Companion() @@ -587,6 +591,7 @@ public abstract class Number : kotlin.Any, java.io.Serializable { public final class Short : kotlin.Number, kotlin.Comparable, java.io.Serializable { /*primary*/ private constructor Short() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -601,6 +606,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Short + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Short public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -613,6 +619,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -638,6 +645,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Short): kotlin.Short public companion object Companion { /*primary*/ private constructor Companion() diff --git a/compiler/testData/builtin-classes/newMethods/kotlin.txt b/compiler/testData/builtin-classes/newMethods/kotlin.txt index abdfdf6bf37..8b84f58d70e 100644 --- a/compiler/testData/builtin-classes/newMethods/kotlin.txt +++ b/compiler/testData/builtin-classes/newMethods/kotlin.txt @@ -53,6 +53,7 @@ public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializ public final class Byte : kotlin.Number, kotlin.Comparable, java.io.Serializable { /*primary*/ private constructor Byte() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Byte): kotlin.Byte public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -67,6 +68,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Byte + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Byte public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -79,6 +81,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Byte): kotlin.Byte public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -104,6 +107,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Byte): kotlin.Byte public companion object Companion { /*primary*/ private constructor Companion() @@ -585,6 +589,7 @@ public abstract class Number : kotlin.Any, java.io.Serializable { public final class Short : kotlin.Number, kotlin.Comparable, java.io.Serializable { /*primary*/ private constructor Short() + @kotlin.SinceKotlin(version = "1.1") public final infix fun and(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int public final operator fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int @@ -599,6 +604,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public final operator fun div(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun div(/*0*/ other: kotlin.Short): kotlin.Int public final operator fun inc(): kotlin.Short + @kotlin.SinceKotlin(version = "1.1") public final fun inv(): kotlin.Short public final operator fun minus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun minus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun minus(/*0*/ other: kotlin.Float): kotlin.Float @@ -611,6 +617,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public final operator fun mod(/*0*/ other: kotlin.Int): kotlin.Int public final operator fun mod(/*0*/ other: kotlin.Long): kotlin.Long public final operator fun mod(/*0*/ other: kotlin.Short): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun or(/*0*/ other: kotlin.Short): kotlin.Short public final operator fun plus(/*0*/ other: kotlin.Byte): kotlin.Int public final operator fun plus(/*0*/ other: kotlin.Double): kotlin.Double public final operator fun plus(/*0*/ other: kotlin.Float): kotlin.Float @@ -636,6 +643,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. public open override /*1*/ fun toShort(): kotlin.Short public final operator fun unaryMinus(): kotlin.Int public final operator fun unaryPlus(): kotlin.Int + @kotlin.SinceKotlin(version = "1.1") public final infix fun xor(/*0*/ other: kotlin.Short): kotlin.Short public companion object Companion { /*primary*/ private constructor Companion() diff --git a/compiler/testData/codegen/box/binaryOp/bitwiseOp.kt b/compiler/testData/codegen/box/binaryOp/bitwiseOp.kt new file mode 100644 index 00000000000..7618481db4c --- /dev/null +++ b/compiler/testData/codegen/box/binaryOp/bitwiseOp.kt @@ -0,0 +1,67 @@ +fun box(): String { + // D = 1101 C = 1100 + // 6 = 0110 5 = 0101 + var iarg1: Int = 0xDC56DC56.toInt() + var iarg2: Int = 0x65DC65DC + var i1 = iarg1 and iarg2 + var i2 = iarg1 or iarg2 + var i3 = iarg1 xor iarg2 + var i4 = iarg1.inv() + var i5 = iarg1 shl 16 + var i6 = iarg1 shr 16 + var i7 = iarg1 ushr 16 + + if (i1 != 0x44544454.toInt()) return "fail: Int.and" + if (i2 != 0xFDDEFDDE.toInt()) return "fail: Int.or" + if (i3 != 0xB98AB98A.toInt()) return "fail: Int.xor" + if (i4 != 0x23A923A9.toInt()) return "fail: Int.inv" + if (i5 != 0xDC560000.toInt()) return "fail: Int.shl" + if (i6 != 0xFFFFDC56.toInt()) return "fail: Int.shr" + if (i7 != 0x0000DC56.toInt()) return "fail: Int.ushr" + + + // TODO: Use long hex constants after KT-4749 is fixed + var larg1: Long = (0xDC56DC56L shl 32) + 0xDC56DC56 // !!!! + var larg2: Long = 0x65DC65DC65DC65DC + var l1 = larg1 and larg2 + var l2 = larg1 or larg2 + var l3 = larg1 xor larg2 + var l4 = larg1.inv() + var l5 = larg1 shl 32 + var l6 = larg1 shr 32 + var l7 = larg1 ushr 32 + + if (l1 != 0x4454445444544454) return "fail: Long.and" + if (l2 != (0xFDDEFDDEL shl 32) + 0xFDDEFDDE) return "fail: Long.or" + if (l3 != (0xB98AB98AL shl 32) + 0xB98AB98A) return "fail: Long.xor" + if (l4 != 0x23A923A923A923A9) return "fail: Long.inv" + if (l5 != (0xDC56DC56L shl 32)/*!!!*/) return "fail: Long.shl" + if (l6 != (0xFFFFFFFFL shl 32) + 0xDC56DC56) return "fail: Long.shr" + if (l7 != (0x00000000L shl 32) + 0xDC56DC56.toLong()) return "fail: Long.ushr" + + var sarg1: Short = 0xDC56.toShort() + var sarg2: Short = 0x65DC.toShort() + var s1 = sarg1 and sarg2 + var s2 = sarg1 or sarg2 + var s3 = sarg1 xor sarg2 + var s4 = sarg1.inv() + + if (s1 != 0x4454.toShort()) return "fail: Short.and" + if (s2 != 0xFDDE.toShort()) return "fail: Short.or" + if (s3 != 0xB98A.toShort()) return "fail: Short.xor" + if (s4 != 0x23A9.toShort()) return "fail: Short.inv" + + var barg1: Byte = 0xDC.toByte() + var barg2: Byte = 0x65.toByte() + var b1 = barg1 and barg2 + var b2 = barg1 or barg2 + var b3 = barg1 xor barg2 + var b4 = barg1.inv() + + if (b1 != 0x44.toByte()) return "fail: Byte.and" + if (b2 != 0xFD.toByte()) return "fail: Byte.or" + if (b3 != 0xB9.toByte()) return "fail: Byte.xor" + if (b4 != 0x23.toByte()) return "fail: Byte.inv" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/binaryOp/bitwiseOpAny.kt b/compiler/testData/codegen/box/binaryOp/bitwiseOpAny.kt new file mode 100644 index 00000000000..035248d5adb --- /dev/null +++ b/compiler/testData/codegen/box/binaryOp/bitwiseOpAny.kt @@ -0,0 +1,67 @@ +fun box(): String { + // D = 1101 C = 1100 + // 6 = 0110 5 = 0101 + var iarg1: Int = 0xDC56DC56.toInt() + var iarg2: Int = 0x65DC65DC + var i1: Any = iarg1 and iarg2 + var i2: Any = iarg1 or iarg2 + var i3: Any = iarg1 xor iarg2 + var i4: Any = iarg1.inv() + var i5: Any = iarg1 shl 16 + var i6: Any = iarg1 shr 16 + var i7: Any = iarg1 ushr 16 + + if (i1 != 0x44544454.toInt()) return "fail: Int.and" + if (i2 != 0xFDDEFDDE.toInt()) return "fail: Int.or" + if (i3 != 0xB98AB98A.toInt()) return "fail: Int.xor" + if (i4 != 0x23A923A9.toInt()) return "fail: Int.inv" + if (i5 != 0xDC560000.toInt()) return "fail: Int.shl" + if (i6 != 0xFFFFDC56.toInt()) return "fail: Int.shr" + if (i7 != 0x0000DC56.toInt()) return "fail: Int.ushr" + + + // TODO: Use long hex constants after KT-4749 is fixed + var larg1: Long = (0xDC56DC56L shl 32) + 0xDC56DC56 // !!!! + var larg2: Long = 0x65DC65DC65DC65DC + var l1: Any = larg1 and larg2 + var l2: Any = larg1 or larg2 + var l3: Any = larg1 xor larg2 + var l4: Any = larg1.inv() + var l5: Any = larg1 shl 32 + var l6: Any = larg1 shr 32 + var l7: Any = larg1 ushr 32 + + if (l1 != 0x4454445444544454) return "fail: Long.and" + if (l2 != (0xFDDEFDDEL shl 32) + 0xFDDEFDDE) return "fail: Long.or" + if (l3 != (0xB98AB98AL shl 32) + 0xB98AB98A) return "fail: Long.xor" + if (l4 != 0x23A923A923A923A9) return "fail: Long.inv" + if (l5 != (0xDC56DC56L shl 32)/*!!!*/) return "fail: Long.shl" + if (l6 != (0xFFFFFFFFL shl 32) + 0xDC56DC56) return "fail: Long.shr" + if (l7 != (0x00000000L shl 32) + 0xDC56DC56.toLong()) return "fail: Long.ushr" + + var sarg1: Short = 0xDC56.toShort() + var sarg2: Short = 0x65DC.toShort() + var s1: Any = sarg1 and sarg2 + var s2: Any = sarg1 or sarg2 + var s3: Any = sarg1 xor sarg2 + var s4: Any = sarg1.inv() + + if (s1 != 0x4454.toShort()) return "fail: Short.and" + if (s2 != 0xFDDE.toShort()) return "fail: Short.or" + if (s3 != 0xB98A.toShort()) return "fail: Short.xor" + if (s4 != 0x23A9.toShort()) return "fail: Short.inv" + + var barg1: Byte = 0xDC.toByte() + var barg2: Byte = 0x65.toByte() + var b1: Any = barg1 and barg2 + var b2: Any = barg1 or barg2 + var b3: Any = barg1 xor barg2 + var b4: Any = barg1.inv() + + if (b1 != 0x44.toByte()) return "fail: Byte.and" + if (b2 != 0xFD.toByte()) return "fail: Byte.or" + if (b3 != 0xB9.toByte()) return "fail: Byte.xor" + if (b4 != 0x23.toByte()) return "fail: Byte.inv" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/binaryOp/bitwiseOpNullable.kt b/compiler/testData/codegen/box/binaryOp/bitwiseOpNullable.kt new file mode 100644 index 00000000000..779f86f9315 --- /dev/null +++ b/compiler/testData/codegen/box/binaryOp/bitwiseOpNullable.kt @@ -0,0 +1,67 @@ +fun box(): String { + // D = 1101 C = 1100 + // 6 = 0110 5 = 0101 + var iarg1: Int = 0xDC56DC56.toInt() + var iarg2: Int = 0x65DC65DC + var i1: Int? = iarg1 and iarg2 + var i2: Int? = iarg1 or iarg2 + var i3: Int? = iarg1 xor iarg2 + var i4: Int? = iarg1.inv() + var i5: Int? = iarg1 shl 16 + var i6: Int? = iarg1 shr 16 + var i7: Int? = iarg1 ushr 16 + + if (i1 != 0x44544454.toInt()) return "fail: Int.and" + if (i2 != 0xFDDEFDDE.toInt()) return "fail: Int.or" + if (i3 != 0xB98AB98A.toInt()) return "fail: Int.xor" + if (i4 != 0x23A923A9.toInt()) return "fail: Int.inv" + if (i5 != 0xDC560000.toInt()) return "fail: Int.shl" + if (i6 != 0xFFFFDC56.toInt()) return "fail: Int.shr" + if (i7 != 0x0000DC56.toInt()) return "fail: Int.ushr" + + + // TODO: Use long hex constants after KT-4749 is fixed + var larg1: Long = (0xDC56DC56L shl 32) + 0xDC56DC56 // !!!! + var larg2: Long = 0x65DC65DC65DC65DC + var l1: Long? = larg1 and larg2 + var l2: Long? = larg1 or larg2 + var l3: Long? = larg1 xor larg2 + var l4: Long? = larg1.inv() + var l5: Long? = larg1 shl 32 + var l6: Long? = larg1 shr 32 + var l7: Long? = larg1 ushr 32 + + if (l1 != 0x4454445444544454) return "fail: Long.and" + if (l2 != (0xFDDEFDDEL shl 32) + 0xFDDEFDDE) return "fail: Long.or" + if (l3 != (0xB98AB98AL shl 32) + 0xB98AB98A) return "fail: Long.xor" + if (l4 != 0x23A923A923A923A9) return "fail: Long.inv" + if (l5 != (0xDC56DC56L shl 32)/*!!!*/) return "fail: Long.shl" + if (l6 != (0xFFFFFFFFL shl 32) + 0xDC56DC56) return "fail: Long.shr" + if (l7 != (0x00000000L shl 32) + 0xDC56DC56.toLong()) return "fail: Long.ushr" + + var sarg1: Short = 0xDC56.toShort() + var sarg2: Short = 0x65DC.toShort() + var s1: Short? = sarg1 and sarg2 + var s2: Short? = sarg1 or sarg2 + var s3: Short? = sarg1 xor sarg2 + var s4: Short? = sarg1.inv() + + if (s1 != 0x4454.toShort()) return "fail: Short.and" + if (s2 != 0xFDDE.toShort()) return "fail: Short.or" + if (s3 != 0xB98A.toShort()) return "fail: Short.xor" + if (s4 != 0x23A9.toShort()) return "fail: Short.inv" + + var barg1: Byte = 0xDC.toByte() + var barg2: Byte = 0x65.toByte() + var b1: Byte? = barg1 and barg2 + var b2: Byte? = barg1 or barg2 + var b3: Byte? = barg1 xor barg2 + var b4: Byte? = barg1.inv() + + if (b1 != 0x44.toByte()) return "fail: Byte.and" + if (b2 != 0xFD.toByte()) return "fail: Byte.or" + if (b3 != 0xB9.toByte()) return "fail: Byte.xor" + if (b4 != 0x23.toByte()) return "fail: Byte.inv" + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 9d8e0a8cf39..f56ae17c566 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -724,6 +724,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/binaryOp"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("bitwiseOp.kt") + public void testBitwiseOp() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/bitwiseOp.kt"); + doTest(fileName); + } + + @TestMetadata("bitwiseOpAny.kt") + public void testBitwiseOpAny() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/bitwiseOpAny.kt"); + doTest(fileName); + } + + @TestMetadata("bitwiseOpNullable.kt") + public void testBitwiseOpNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/bitwiseOpNullable.kt"); + doTest(fileName); + } + @TestMetadata("call.kt") public void testCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/call.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 278038e6b77..a06b31b3eb2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -724,6 +724,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/binaryOp"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("bitwiseOp.kt") + public void testBitwiseOp() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/bitwiseOp.kt"); + doTest(fileName); + } + + @TestMetadata("bitwiseOpAny.kt") + public void testBitwiseOpAny() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/bitwiseOpAny.kt"); + doTest(fileName); + } + + @TestMetadata("bitwiseOpNullable.kt") + public void testBitwiseOpNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/bitwiseOpNullable.kt"); + doTest(fileName); + } + @TestMetadata("call.kt") public void testCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/binaryOp/call.kt"); diff --git a/core/builtins/native/kotlin/Primitives.kt b/core/builtins/native/kotlin/Primitives.kt index 1eea4ea60ec..8d0a9d88c53 100644 --- a/core/builtins/native/kotlin/Primitives.kt +++ b/core/builtins/native/kotlin/Primitives.kt @@ -160,6 +160,19 @@ public class Byte private constructor() : Number(), Comparable { /** Creates a range from this value to the specified [other] value. */ public operator fun rangeTo(other: Long): LongRange + /** Performs a bitwise AND operation between the two values. */ + @SinceKotlin("1.1") + public infix fun and(other: Byte): Byte + /** Performs a bitwise OR operation between the two values. */ + @SinceKotlin("1.1") + public infix fun or(other: Byte): Byte + /** Performs a bitwise XOR operation between the two values. */ + @SinceKotlin("1.1") + public infix fun xor(other: Byte): Byte + /** Inverts the bits in this value/ */ + @SinceKotlin("1.1") + public fun inv(): Byte + public override fun toByte(): Byte public override fun toChar(): Char public override fun toShort(): Short @@ -311,6 +324,19 @@ public class Short private constructor() : Number(), Comparable { /** Creates a range from this value to the specified [other] value. */ public operator fun rangeTo(other: Long): LongRange + /** Performs a bitwise AND operation between the two values. */ + @SinceKotlin("1.1") + public infix fun and(other: Short): Short + /** Performs a bitwise OR operation between the two values. */ + @SinceKotlin("1.1") + public infix fun or(other: Short): Short + /** Performs a bitwise XOR operation between the two values. */ + @SinceKotlin("1.1") + public infix fun xor(other: Short): Short + /** Inverts the bits in this value/ */ + @SinceKotlin("1.1") + public fun inv(): Short + public override fun toByte(): Byte public override fun toChar(): Char public override fun toShort(): Short diff --git a/generators/src/org/jetbrains/kotlin/generators/builtins/primitives.kt b/generators/src/org/jetbrains/kotlin/generators/builtins/primitives.kt index 2b348e98fd9..6487f424aa9 100644 --- a/generators/src/org/jetbrains/kotlin/generators/builtins/primitives.kt +++ b/generators/src/org/jetbrains/kotlin/generators/builtins/primitives.kt @@ -119,7 +119,10 @@ class GeneratePrimitives(out: PrintWriter) : BuiltInsSourceGenerator(out) { generateRangeTo(kind) if (kind == PrimitiveType.INT || kind == PrimitiveType.LONG) { - generateBitwiseOperators(className) + generateBitShiftOperators(className) + } + if (kind == PrimitiveType.INT || kind == PrimitiveType.LONG || kind == PrimitiveType.BYTE || kind == PrimitiveType.SHORT) { + generateBitwiseOperators(className, since = if (kind == PrimitiveType.BYTE || kind == PrimitiveType.SHORT) "1.1" else null) } generateConversions(kind) @@ -189,16 +192,20 @@ class GeneratePrimitives(out: PrintWriter) : BuiltInsSourceGenerator(out) { out.println() } - private fun generateBitwiseOperators(className: String) { + private fun generateBitShiftOperators(className: String) { for ((name, doc) in shiftOperators) { out.println(" /** $doc */") out.println(" public infix fun $name(bitCount: Int): $className") } + } + private fun generateBitwiseOperators(className: String, since: String?) { for ((name, doc) in bitwiseOperators) { out.println(" /** $doc */") + since?.let { out.println(" @SinceKotlin(\"$it\")") } out.println(" public infix fun $name(other: $className): $className") } out.println(" /** Inverts the bits in this value/ */") + since?.let { out.println(" @SinceKotlin(\"$it\")") } out.println(" public fun inv(): $className") out.println() }