Generate switch instruction for 'when' with unsigned subject

This commit is contained in:
Dmitry Petrov
2019-01-16 14:03:33 +03:00
parent 3c2d026128
commit c1de845d29
10 changed files with 100 additions and 5 deletions
@@ -22,10 +22,7 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.IntegerValueConstant
import org.jetbrains.kotlin.resolve.constants.NullValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.org.objectweb.asm.Type
import java.util.ArrayList
@@ -102,7 +99,7 @@ private constructor(
private fun isIntegralConstantsSwitch(expression: KtWhenExpression, subjectType: Type): Boolean =
AsmUtil.isIntPrimitive(subjectType) &&
checkAllItemsAreConstantsSatisfying(expression) { it is IntegerValueConstant<*> }
checkAllItemsAreConstantsSatisfying(expression) { it is IntegerValueConstant<*> || it is UnsignedValueConstant<*> }
private fun isStringConstantsSwitch(expression: KtWhenExpression, subjectType: Type): Boolean =
subjectType.className == String::class.java.name &&
@@ -0,0 +1,35 @@
// WITH_RUNTIME
// IGNORE_BACKEND: JS, JVM_IR
const val M1: UInt = 2147483648u
const val M2: ULong = 9223372036854775808UL
fun testUInt(x: UInt) =
when (x) {
0u -> "none"
1u -> "one"
2u -> "two"
3u -> "three"
M1 -> "M1"
else -> "many"
}
fun testULong(x: ULong) =
when (x) {
0UL -> "none"
1UL -> "one"
2UL -> "two"
3UL -> "three"
M2 -> "M2"
else -> "many"
}
fun box(): String {
val t1 = listOf(0u, 1u, 2u, 3u, 4u, M1).map { testUInt(it) }
if (t1 != listOf("none", "one", "two", "three", "many", "M1")) throw AssertionError("UInt: $t1")
val t2 = listOf(0UL, 1UL, 2UL, 3UL, 4UL, M2).map { testULong(it) }
if (t2 != listOf("none", "one", "two", "three", "many", "M2")) throw AssertionError("ULong: $t2")
return "OK"
}
@@ -0,0 +1,28 @@
// WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
const val M1: UInt = 2147483648u
fun testUInt1(x: UInt) =
when (x) {
0u -> "none"
1u -> "one"
2u -> "two"
3u -> "three"
else -> "many"
}
fun testUInt2(x: UInt) =
when (x) {
0u -> "none"
1u -> "one"
2u -> "two"
3u -> "three"
M1 -> "M1"
else -> "many"
}
// 2 SWITCH
// ^ This captures both TABLESWITCH and LOOKUPSWITCH; we don't care about nuances of *SWITCH instruction generation here.
// 0 IF_ICMP
@@ -24357,6 +24357,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testVarargsOfUnsignedTypes() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt");
}
@TestMetadata("whenByUnsigned.kt")
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -3182,6 +3182,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
public void testUnsignedLongRemainder_jvm18() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongRemainder_jvm18.kt");
}
@TestMetadata("whenByUnsigned.kt")
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/whenByUnsigned.kt");
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/varargs")
@@ -3182,6 +3182,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
public void testUnsignedLongRemainder_jvm18() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongRemainder_jvm18.kt");
}
@TestMetadata("whenByUnsigned.kt")
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/whenByUnsigned.kt");
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/varargs")
@@ -24357,6 +24357,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testVarargsOfUnsignedTypes() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt");
}
@TestMetadata("whenByUnsigned.kt")
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -24362,6 +24362,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testVarargsOfUnsignedTypes() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt");
}
@TestMetadata("whenByUnsigned.kt")
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -18797,6 +18797,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testVarargsOfUnsignedTypes() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt");
}
@TestMetadata("whenByUnsigned.kt")
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")
@@ -19847,6 +19847,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
public void testVarargsOfUnsignedTypes() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/varargsOfUnsignedTypes.kt");
}
@TestMetadata("whenByUnsigned.kt")
public void testWhenByUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/whenByUnsigned.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/vararg")