JVM_IR: Generate more line numbers for intrinsic comparisons.

Otherwise, if complex expressions such as when expressions are
used in combination with the intrinsics we get incorrect stepping
behavior.

^KT-64341 Fixed
This commit is contained in:
Mads Ager
2023-12-13 12:43:05 +01:00
committed by Space Cloud
parent a441a82357
commit e41a1247e2
23 changed files with 723 additions and 54 deletions
@@ -601,6 +601,48 @@ public class FirLightTreeSteppingTestGenerated extends AbstractFirLightTreeStepp
runTest("compiler/testData/debug/stepping/whenExpr.kt");
}
@Test
@TestMetadata("whenInConjunction.kt")
public void testWhenInConjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInConjunction.kt");
}
@Test
@TestMetadata("whenInDisjunction.kt")
public void testWhenInDisjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInDisjunction.kt");
}
@Test
@TestMetadata("whenInGeneralObjectComparison.kt")
public void testWhenInGeneralObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInGeneralObjectComparison.kt");
}
@Test
@TestMetadata("whenInNegation.kt")
public void testWhenInNegation() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNegation.kt");
}
@Test
@TestMetadata("whenInNullComparison.kt")
public void testWhenInNullComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNullComparison.kt");
}
@Test
@TestMetadata("whenInPrimitiveToObjectComparison.kt")
public void testWhenInPrimitiveToObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInPrimitiveToObjectComparison.kt");
}
@Test
@TestMetadata("whenInZeroComparison.kt")
public void testWhenInZeroComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInZeroComparison.kt");
}
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
@@ -601,6 +601,48 @@ public class FirPsiSteppingTestGenerated extends AbstractFirPsiSteppingTest {
runTest("compiler/testData/debug/stepping/whenExpr.kt");
}
@Test
@TestMetadata("whenInConjunction.kt")
public void testWhenInConjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInConjunction.kt");
}
@Test
@TestMetadata("whenInDisjunction.kt")
public void testWhenInDisjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInDisjunction.kt");
}
@Test
@TestMetadata("whenInGeneralObjectComparison.kt")
public void testWhenInGeneralObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInGeneralObjectComparison.kt");
}
@Test
@TestMetadata("whenInNegation.kt")
public void testWhenInNegation() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNegation.kt");
}
@Test
@TestMetadata("whenInNullComparison.kt")
public void testWhenInNullComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNullComparison.kt");
}
@Test
@TestMetadata("whenInPrimitiveToObjectComparison.kt")
public void testWhenInPrimitiveToObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInPrimitiveToObjectComparison.kt");
}
@Test
@TestMetadata("whenInZeroComparison.kt")
public void testWhenInZeroComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInZeroComparison.kt");
}
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.isSingleFieldValueClass
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.isTypeParameter
@@ -110,6 +111,12 @@ abstract class BooleanValue(codegen: ExpressionCodegen) :
StackValue.coerce(Type.BOOLEAN_TYPE, target, mv)
}
}
fun markLineNumber(expression: IrExpression) {
with(codegen) {
expression.markLineNumber(startOffset = true)
}
}
}
class BooleanConstant(codegen: ExpressionCodegen, val value: Boolean) : BooleanValue(codegen) {
@@ -12,25 +12,41 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.org.objectweb.asm.Label
object AndAnd : IntrinsicMethod() {
private class BooleanConjunction(val arg0: IrExpression, val arg1: IrExpression, codegen: ExpressionCodegen, val data: BlockInfo) :
BooleanValue(codegen) {
private class BooleanConjunction(
val left: IrExpression,
val right: IrExpression,
codegen: ExpressionCodegen,
val data: BlockInfo
) : BooleanValue(codegen) {
override fun jumpIfFalse(target: Label) {
arg0.accept(codegen, data).coerceToBoolean().jumpIfFalse(target)
arg1.accept(codegen, data).coerceToBoolean().jumpIfFalse(target)
val leftValue = left.accept(codegen, data).coerceToBoolean()
markLineNumber(left)
leftValue.jumpIfFalse(target)
val rightValue = right.accept(codegen, data).coerceToBoolean()
markLineNumber(right)
rightValue.jumpIfFalse(target)
}
override fun jumpIfTrue(target: Label) {
val stayLabel = Label()
arg0.accept(codegen, data).coerceToBoolean().jumpIfFalse(stayLabel)
arg1.accept(codegen, data).coerceToBoolean().jumpIfTrue(target)
val leftValue = left.accept(codegen, data).coerceToBoolean()
markLineNumber(left)
leftValue.jumpIfFalse(stayLabel)
val rightValue = right.accept(codegen, data).coerceToBoolean()
markLineNumber(right)
rightValue.jumpIfTrue(target)
mv.visitLabel(stayLabel)
}
override fun discard() {
val end = Label()
arg0.accept(codegen, data).coerceToBoolean().jumpIfFalse(end)
arg1.accept(codegen, data).discard()
val leftValue = left.accept(codegen, data).coerceToBoolean()
markLineNumber(left)
leftValue.jumpIfFalse(end)
val rightValue = right.accept(codegen, data)
markLineNumber(right)
rightValue.discard()
mv.visitLabel(end)
}
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.codegen.BranchedValue
import org.jetbrains.kotlin.codegen.NumberCompare
import org.jetbrains.kotlin.codegen.ObjectCompare
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
@@ -67,27 +68,37 @@ object CompareTo : IntrinsicMethod() {
}
}
class IntegerZeroComparison(val a: MaterialValue) : BooleanValue(a.codegen) {
class IntegerZeroComparison(val nonZeroExpression: IrExpression, val a: MaterialValue) : BooleanValue(a.codegen) {
override fun jumpIfFalse(target: Label) {
markLineNumber(nonZeroExpression)
mv.visitJumpInsn(Opcodes.IFNE, target)
}
override fun jumpIfTrue(target: Label) {
markLineNumber(nonZeroExpression)
mv.visitJumpInsn(Opcodes.IFEQ, target)
}
override fun discard() {
markLineNumber(nonZeroExpression)
a.discard()
}
}
class BooleanComparison(val op: IElementType, val a: MaterialValue, val b: MaterialValue) : BooleanValue(a.codegen) {
class BooleanComparison(
val expression: IrFunctionAccessExpression,
val op: IElementType,
val a: MaterialValue,
val b: MaterialValue
) : BooleanValue(a.codegen) {
override fun jumpIfFalse(target: Label) {
// TODO 1. get rid of the dependency; 2. take `b.type` into account.
val opcode = if (a.type.sort == Type.OBJECT)
ObjectCompare.getObjectCompareOpcode(op)
else
NumberCompare.patchOpcode(NumberCompare.getNumberCompareOpcode(op), mv, op, a.type)
markLineNumber(expression)
mv.visitJumpInsn(opcode, target)
}
@@ -96,17 +107,23 @@ class BooleanComparison(val op: IElementType, val a: MaterialValue, val b: Mater
BranchedValue.negatedOperations[ObjectCompare.getObjectCompareOpcode(op)]!!
else
NumberCompare.patchOpcode(BranchedValue.negatedOperations[NumberCompare.getNumberCompareOpcode(op)]!!, mv, op, a.type)
markLineNumber(expression)
mv.visitJumpInsn(opcode, target)
}
override fun discard() {
markLineNumber(expression)
b.discard()
a.discard()
}
}
class NonIEEE754FloatComparison(op: IElementType, private val a: MaterialValue, private val b: MaterialValue) : BooleanValue(a.codegen) {
class NonIEEE754FloatComparison(
private val expression: IrFunctionAccessExpression,
op: IElementType,
private val a: MaterialValue,
private val b: MaterialValue
) : BooleanValue(a.codegen) {
private val numberCompareOpcode = NumberCompare.getNumberCompareOpcode(op)
private fun invokeStaticComparison(type: Type) {
@@ -118,22 +135,26 @@ class NonIEEE754FloatComparison(op: IElementType, private val a: MaterialValue,
}
override fun jumpIfFalse(target: Label) {
markLineNumber(expression)
invokeStaticComparison(a.type)
mv.visitJumpInsn(numberCompareOpcode, target)
}
override fun jumpIfTrue(target: Label) {
markLineNumber(expression)
invokeStaticComparison(a.type)
mv.visitJumpInsn(BranchedValue.negatedOperations[numberCompareOpcode]!!, target)
}
override fun discard() {
markLineNumber(expression)
b.discard()
a.discard()
}
}
class PrimitiveToObjectComparison(
private val expression: IrFunctionAccessExpression,
private val op: IElementType,
private val leftIsPrimitive: Boolean,
private val left: MaterialValue,
@@ -159,26 +180,31 @@ class PrimitiveToObjectComparison(
mv.mark(compareLabel)
// Type checking OK, can unbox and compare:
return if (leftIsPrimitive) {
BooleanComparison(op, left, right.materializedAt(left.type, right.irType))
BooleanComparison(expression, op, left, right.materializedAt(left.type, right.irType))
} else {
val leftUnboxed = left.materializedAt(right.type, left.irType)
mv.load(tmp, right.type)
codegen.frameMap.leaveTemp(right.type)
BooleanComparison(op, leftUnboxed, right)
BooleanComparison(expression, op, leftUnboxed, right)
}
}
override fun jumpIfFalse(target: Label) {
checkTypeAndCompare(target).jumpIfFalse(target)
markLineNumber(expression)
val comparison = checkTypeAndCompare(target)
comparison.jumpIfFalse(target)
}
override fun jumpIfTrue(target: Label) {
markLineNumber(expression)
val wrongType = Label()
checkTypeAndCompare(wrongType).jumpIfTrue(target)
val comparison = checkTypeAndCompare(wrongType)
comparison.jumpIfTrue(target)
mv.mark(wrongType)
}
override fun discard() {
markLineNumber(expression)
right.discard()
left.discard()
}
@@ -200,9 +226,9 @@ class PrimitiveComparison(
&& (left.isSmartcastFromHigherThanNullable(codegen.context) || right.isSmartcastFromHigherThanNullable(codegen.context))
return if (useNonIEEE754Comparison) {
NonIEEE754FloatComparison(operatorToken, a, b)
NonIEEE754FloatComparison(expression, operatorToken, a, b)
} else {
BooleanComparison(operatorToken, a, b)
BooleanComparison(expression, operatorToken, a, b)
}
}
}
@@ -57,10 +57,21 @@ class ExplicitEquals : IntrinsicMethod() {
class Equals(val operator: IElementType) : IntrinsicMethod() {
private class BooleanNullCheck(val value: PromisedValue) : BooleanValue(value.codegen) {
override fun jumpIfFalse(target: Label) = value.materialize().also { mv.ifnonnull(target) }
override fun jumpIfTrue(target: Label) = value.materialize().also { mv.ifnull(target) }
private class BooleanNullCheck(val expression: IrFunctionAccessExpression, val value: PromisedValue) : BooleanValue(value.codegen) {
override fun jumpIfFalse(target: Label) {
value.materialize()
markLineNumber(expression)
mv.ifnonnull(target)
}
override fun jumpIfTrue(target: Label) {
value.materialize()
markLineNumber(expression)
mv.ifnull(target)
}
override fun discard() {
markLineNumber(expression)
value.discard()
}
}
@@ -71,7 +82,7 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
val irValue = if (a.isNullConst()) b else a
val value = irValue.accept(codegen, data)
return if (!isPrimitive(value.type) && (irValue.type.classOrNull?.owner?.isSingleFieldValueClass != true || irValue.type.isNullable()))
BooleanNullCheck(value)
BooleanNullCheck(expression, value)
else {
value.discard()
BooleanConstant(codegen, false)
@@ -80,7 +91,7 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
val leftType = codegen.typeMapper.mapTypeAsDeclaration(a.type)
if (expression.origin == IrStatementOrigin.EQEQEQ || expression.origin == IrStatementOrigin.EXCLEQEQ) {
return referenceEquals(a, b, leftType, codegen, data)
return referenceEquals(expression, a, b, leftType, codegen, data)
}
val rightType = codegen.typeMapper.mapTypeAsDeclaration(b.type)
@@ -93,7 +104,7 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
) {
val aValue = a.accept(codegen, data).materializedAt(leftType, a.type)
val bValue = b.accept(codegen, data).materializedAt(rightType, b.type)
return PrimitiveToObjectComparison(operator, AsmUtil.isIntOrLongPrimitive(leftType), aValue, bValue)
return PrimitiveToObjectComparison(expression, operator, AsmUtil.isIntOrLongPrimitive(leftType), aValue, bValue)
}
if (isPrimitive(leftType) && leftType == rightType) {
@@ -101,26 +112,29 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
return if (leftType == Type.FLOAT_TYPE || leftType == Type.DOUBLE_TYPE) {
val aValue = a.accept(codegen, data).materializedAt(leftType, a.type)
val bValue = b.accept(codegen, data).materializedAt(rightType, b.type)
return NonIEEE754FloatComparison(operator, aValue, bValue)
return NonIEEE754FloatComparison(expression, operator, aValue, bValue)
} else {
referenceEquals(a, b, leftType, codegen, data)
referenceEquals(expression, a, b, leftType, codegen, data)
}
}
// We can use reference equality for enums, otherwise we fall back to boxed equality.
return when {
a.isEnumValue || b.isEnumValue ->
referenceEquals(a, b, leftType, codegen, data)
referenceEquals(expression, a, b, leftType, codegen, data)
a.isClassValue && b.isClassValue -> {
val leftValue = codegen.generateClassLiteralReference(a, wrapIntoKClass = false, wrapPrimitives = true, data = data)
val rightValue = codegen.generateClassLiteralReference(b, wrapIntoKClass = false, wrapPrimitives = true, data = data)
BooleanComparison(operator, leftValue, rightValue)
BooleanComparison(expression, operator, leftValue, rightValue)
}
else -> {
a.accept(codegen, data).materializeAt(AsmTypes.OBJECT_TYPE, codegen.context.irBuiltIns.anyNType)
b.accept(codegen, data).materializeAt(AsmTypes.OBJECT_TYPE, codegen.context.irBuiltIns.anyNType)
with(codegen) {
expression.markLineNumber(startOffset = true)
}
genAreEqualCall(codegen.mv)
MaterialValue(codegen, Type.BOOLEAN_TYPE, codegen.context.irBuiltIns.booleanType)
}
@@ -128,6 +142,7 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
}
private fun referenceEquals(
expression: IrFunctionAccessExpression,
left: IrExpression,
right: IrExpression,
leftType: Type,
@@ -137,11 +152,11 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
val operandType = if (!isPrimitive(leftType)) AsmTypes.OBJECT_TYPE else leftType
return if (operandType == Type.INT_TYPE && (left.isIntegerConst(0) || right.isIntegerConst(0))) {
val nonZero = if (left.isIntegerConst(0)) right else left
IntegerZeroComparison(nonZero.accept(codegen, data).materializedAt(operandType, nonZero.type))
IntegerZeroComparison(expression, nonZero.accept(codegen, data).materializedAt(operandType, nonZero.type))
} else {
val leftValue = left.accept(codegen, data).materializedAt(operandType, left.type)
val rightValue = right.accept(codegen, data).materializedAt(operandType, right.type)
BooleanComparison(operator, leftValue, rightValue)
BooleanComparison(expression, operator, leftValue, rightValue)
}
}
@@ -22,16 +22,26 @@ import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.codegen.coerceToBoolean
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.org.objectweb.asm.Label
import kotlin.math.exp
object Not : IntrinsicMethod() {
class BooleanNegation(val value: BooleanValue) : BooleanValue(value.codegen) {
override fun jumpIfFalse(target: Label) = value.jumpIfTrue(target)
override fun jumpIfTrue(target: Label) = value.jumpIfFalse(target)
class BooleanNegation(val expression: IrFunctionAccessExpression, val value: BooleanValue) : BooleanValue(value.codegen) {
override fun jumpIfFalse(target: Label) {
markLineNumber(expression)
value.jumpIfTrue(target)
}
override fun jumpIfTrue(target: Label) {
markLineNumber(expression)
value.jumpIfFalse(target)
}
override fun discard() {
markLineNumber(expression)
value.discard()
}
}
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo) =
BooleanNegation(expression.dispatchReceiver!!.accept(codegen, data).coerceToBoolean())
BooleanNegation(expression, expression.dispatchReceiver!!.accept(codegen, data).coerceToBoolean())
}
@@ -14,25 +14,37 @@ import org.jetbrains.org.objectweb.asm.Label
object OrOr : IntrinsicMethod() {
private class BooleanDisjunction(
val arg0: IrExpression, val arg1: IrExpression, codegen: ExpressionCodegen, val data: BlockInfo
val left: IrExpression, val right: IrExpression, codegen: ExpressionCodegen, val data: BlockInfo
) : BooleanValue(codegen) {
override fun jumpIfFalse(target: Label) {
val stayLabel = Label()
arg0.accept(codegen, data).coerceToBoolean().jumpIfTrue(stayLabel)
arg1.accept(codegen, data).coerceToBoolean().jumpIfFalse(target)
val leftValue = left.accept(codegen, data).coerceToBoolean()
markLineNumber(left)
leftValue.jumpIfTrue(stayLabel)
val rightValue = right.accept(codegen, data).coerceToBoolean()
markLineNumber(right)
rightValue.jumpIfFalse(target)
mv.visitLabel(stayLabel)
}
override fun jumpIfTrue(target: Label) {
arg0.accept(codegen, data).coerceToBoolean().jumpIfTrue(target)
arg1.accept(codegen, data).coerceToBoolean().jumpIfTrue(target)
val leftValue = left.accept(codegen, data).coerceToBoolean()
markLineNumber(left)
leftValue.jumpIfTrue(target)
val rightValue = right.accept(codegen, data).coerceToBoolean()
markLineNumber(right)
rightValue.jumpIfTrue(target)
}
override fun discard() {
val end = Label()
arg0.accept(codegen, data).coerceToBoolean().jumpIfTrue(end)
arg1.accept(codegen, data).discard()
val leftValue = left.accept(codegen, data).coerceToBoolean()
markLineNumber(left)
leftValue.jumpIfTrue(end)
val rightValue = right.accept(codegen, data)
markLineNumber(right)
rightValue.discard()
mv.visitLabel(end)
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ inline fun getB(): Int {
// test.kt:15 box
// test.kt:7 box
// test.kt:12 getA
// test.kt:7 box
// test.kt:6 box
// test.kt:9 box
// test.kt:15 box
// test.kt:9 box
+43
View File
@@ -0,0 +1,43 @@
// IGNORE_BACKEND: WASM
// FILE: test.kt
fun foo(n: Number) {
if (n.toInt() > 1 && when (n) {
is Float -> true
else -> false
}) {
}
if (when (n) {
is Float -> true
else -> false
} && n.toInt() > 1) {
}
}
fun box() {
foo(2.0f)
}
// EXPECTATIONS JVM_IR
// test.kt:18 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:10 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:13 foo
// test.kt:15 foo
// test.kt:19 box
// EXPECTATIONS JS_IR
// test.kt:18 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:6 foo
// test.kt:11 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:13 foo
// test.kt:15 foo
// test.kt:19 box
+43
View File
@@ -0,0 +1,43 @@
// IGNORE_BACKEND: WASM
// FILE: test.kt
fun foo(n: Number) {
if (n.toInt() < 1 || when (n) {
is Float -> false
else -> true
}) {
}
if (when (n) {
is Float -> false
else -> true
} || n.toInt() > 1) {
}
}
fun box() {
foo(2.0f)
}
// EXPECTATIONS JVM_IR
// test.kt:18 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:10 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:13 foo
// test.kt:15 foo
// test.kt:19 box
// EXPECTATIONS JS_IR
// test.kt:18 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:6 foo
// test.kt:11 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:13 foo
// test.kt:15 foo
// test.kt:19 box
@@ -0,0 +1,65 @@
// IGNORE_BACKEND: WASM
// FILE: test.kt
fun foo(n: Any, other: Any) {
if (other == when (n) {
is Int -> n
else -> 1.0f
}) {
}
if (when (n) {
is Int -> n
else -> 1.0f
} == other) {
}
if (other != when (n) {
is Int -> n
else -> 1.0f
}) {
}
if (when (n) {
is Int -> n
else -> 1.0f
} != other) {
}
}
fun box() {
foo(2, Any())
}
// EXPECTATIONS JVM_IR
// test.kt:28 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:10 foo
// test.kt:11 foo
// test.kt:13 foo
// test.kt:10 foo
// test.kt:15 foo
// test.kt:16 foo
// test.kt:15 foo
// test.kt:20 foo
// test.kt:21 foo
// test.kt:23 foo
// test.kt:20 foo
// test.kt:25 foo
// test.kt:29 box
// EXPECTATIONS JS_IR
// test.kt:28 box
// test.kt:6 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:11 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:16 foo
// test.kt:16 foo
// test.kt:15 foo
// test.kt:21 foo
// test.kt:21 foo
// test.kt:20 foo
// test.kt:25 foo
// test.kt:29 box
+29
View File
@@ -0,0 +1,29 @@
// IGNORE_BACKEND: WASM
// FILE: test.kt
fun foo(n: Number) {
if (!when (n) {
is Float -> false
else -> true
}) {
}
}
fun box() {
foo(2.0f)
}
// EXPECTATIONS JVM_IR
// test.kt:13 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:10 foo
// test.kt:14 box
// EXPECTATIONS JS_IR
// test.kt:13 box
// test.kt:6 foo
// test.kt:6 foo
// test.kt:10 foo
// test.kt:14 box
@@ -0,0 +1,39 @@
// IGNORE_BACKEND: WASM
// FILE: test.kt
fun foo(n: Number) {
if (when (n) {
is Float -> null
else -> 32
} == null) {
}
if (when (n) {
is Float -> null
else -> 32
} != null) {
}
}
fun box() {
foo(2.0f)
}
// EXPECTATIONS JVM_IR
// test.kt:18 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:10 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:15 foo
// test.kt:19 box
// EXPECTATIONS JS_IR
// test.kt:18 box
// test.kt:6 foo
// test.kt:6 foo
// test.kt:11 foo
// test.kt:11 foo
// test.kt:15 foo
// test.kt:19 box
@@ -0,0 +1,41 @@
// IGNORE_BACKEND: WASM
// FILE: test.kt
fun foo(n: Any) {
if (1 == when (n) {
is Int -> n
else -> 1.0f
}) {
}
if (1 != when (n) {
is Int -> n
else -> 1.0f
}) {
}
}
fun box() {
foo(2)
}
// EXPECTATIONS JVM_IR
// test.kt:18 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:10 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:15 foo
// test.kt:19 box
// EXPECTATIONS JS_IR
// test.kt:18 box
// test.kt:6 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:11 foo
// test.kt:11 foo
// test.kt:10 foo
// test.kt:15 foo
// test.kt:19 box
@@ -0,0 +1,29 @@
// IGNORE_BACKEND: WASM
// FILE: test.kt
fun foo(n: Number) {
if (when (n) {
is Float -> 1
else -> 0
} == 0) {
}
}
fun box() {
foo(2.0f)
}
// EXPECTATIONS JVM_IR
// test.kt:13 box
// test.kt:5 foo
// test.kt:6 foo
// test.kt:5 foo
// test.kt:10 foo
// test.kt:14 box
// EXPECTATIONS JS_IR
// test.kt:13 box
// test.kt:6 foo
// test.kt:6 foo
// test.kt:10 foo
// test.kt:14 box
@@ -601,6 +601,48 @@ public class IrSteppingWithBytecodeInlinerTestGenerated extends AbstractIrSteppi
runTest("compiler/testData/debug/stepping/whenExpr.kt");
}
@Test
@TestMetadata("whenInConjunction.kt")
public void testWhenInConjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInConjunction.kt");
}
@Test
@TestMetadata("whenInDisjunction.kt")
public void testWhenInDisjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInDisjunction.kt");
}
@Test
@TestMetadata("whenInGeneralObjectComparison.kt")
public void testWhenInGeneralObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInGeneralObjectComparison.kt");
}
@Test
@TestMetadata("whenInNegation.kt")
public void testWhenInNegation() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNegation.kt");
}
@Test
@TestMetadata("whenInNullComparison.kt")
public void testWhenInNullComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNullComparison.kt");
}
@Test
@TestMetadata("whenInPrimitiveToObjectComparison.kt")
public void testWhenInPrimitiveToObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInPrimitiveToObjectComparison.kt");
}
@Test
@TestMetadata("whenInZeroComparison.kt")
public void testWhenInZeroComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInZeroComparison.kt");
}
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
@@ -601,6 +601,48 @@ public class IrSteppingWithIrInlinerTestGenerated extends AbstractIrSteppingWith
runTest("compiler/testData/debug/stepping/whenExpr.kt");
}
@Test
@TestMetadata("whenInConjunction.kt")
public void testWhenInConjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInConjunction.kt");
}
@Test
@TestMetadata("whenInDisjunction.kt")
public void testWhenInDisjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInDisjunction.kt");
}
@Test
@TestMetadata("whenInGeneralObjectComparison.kt")
public void testWhenInGeneralObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInGeneralObjectComparison.kt");
}
@Test
@TestMetadata("whenInNegation.kt")
public void testWhenInNegation() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNegation.kt");
}
@Test
@TestMetadata("whenInNullComparison.kt")
public void testWhenInNullComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNullComparison.kt");
}
@Test
@TestMetadata("whenInPrimitiveToObjectComparison.kt")
public void testWhenInPrimitiveToObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInPrimitiveToObjectComparison.kt");
}
@Test
@TestMetadata("whenInZeroComparison.kt")
public void testWhenInZeroComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInZeroComparison.kt");
}
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
@@ -595,6 +595,48 @@ public class IrJsSteppingTestGenerated extends AbstractIrJsSteppingTest {
runTest("compiler/testData/debug/stepping/whenExpr.kt");
}
@Test
@TestMetadata("whenInConjunction.kt")
public void testWhenInConjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInConjunction.kt");
}
@Test
@TestMetadata("whenInDisjunction.kt")
public void testWhenInDisjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInDisjunction.kt");
}
@Test
@TestMetadata("whenInGeneralObjectComparison.kt")
public void testWhenInGeneralObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInGeneralObjectComparison.kt");
}
@Test
@TestMetadata("whenInNegation.kt")
public void testWhenInNegation() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNegation.kt");
}
@Test
@TestMetadata("whenInNullComparison.kt")
public void testWhenInNullComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNullComparison.kt");
}
@Test
@TestMetadata("whenInPrimitiveToObjectComparison.kt")
public void testWhenInPrimitiveToObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInPrimitiveToObjectComparison.kt");
}
@Test
@TestMetadata("whenInZeroComparison.kt")
public void testWhenInZeroComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInZeroComparison.kt");
}
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
@@ -643,16 +643,16 @@ public final class OptionalUser : java/lang/Object {
LDC ()
LDC ()
INVOKESPECIAL (User, <init>, (Ljava/lang/String;Ljava/lang/String;)V)
LABEL (L4)
LINENUMBER (9)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, areEqual, (Ljava/lang/Object;Ljava/lang/Object;)Z)
IFNE (L4)
IFNE (L5)
ICONST_1
GOTO (L2)
LABEL (L4)
LABEL (L5)
ICONST_0
LABEL (L2)
IFEQ (L5)
LABEL (L6)
LINENUMBER (9)
IFEQ (L6)
ALOAD (1)
ALOAD (2)
ICONST_0
@@ -661,7 +661,7 @@ public final class OptionalUser : java/lang/Object {
ALOAD (0)
GETFIELD (OptionalUser, user, LUser;)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V)
LABEL (L5)
LABEL (L6)
RETURN
LABEL (L7)
}
@@ -681,16 +681,16 @@ public final class OptionalUser : java/lang/Object {
LDC ()
LDC ()
INVOKESPECIAL (User, <init>, (Ljava/lang/String;Ljava/lang/String;)V)
LABEL (L4)
LINENUMBER (9)
INVOKESTATIC (kotlin/jvm/internal/Intrinsics, areEqual, (Ljava/lang/Object;Ljava/lang/Object;)Z)
IFNE (L4)
IFNE (L5)
ICONST_1
GOTO (L2)
LABEL (L4)
LABEL (L5)
ICONST_0
LABEL (L2)
IFEQ (L5)
LABEL (L6)
LINENUMBER (9)
IFEQ (L6)
ALOAD (1)
ALOAD (2)
ICONST_0
@@ -699,7 +699,7 @@ public final class OptionalUser : java/lang/Object {
ALOAD (0)
GETFIELD (OptionalUser, user, LUser;)
INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V)
LABEL (L5)
LABEL (L6)
RETURN
LABEL (L7)
}
@@ -595,6 +595,48 @@ public class FirWasmSteppingTestGenerated extends AbstractFirWasmSteppingTest {
runTest("compiler/testData/debug/stepping/whenExpr.kt");
}
@Test
@TestMetadata("whenInConjunction.kt")
public void testWhenInConjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInConjunction.kt");
}
@Test
@TestMetadata("whenInDisjunction.kt")
public void testWhenInDisjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInDisjunction.kt");
}
@Test
@TestMetadata("whenInGeneralObjectComparison.kt")
public void testWhenInGeneralObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInGeneralObjectComparison.kt");
}
@Test
@TestMetadata("whenInNegation.kt")
public void testWhenInNegation() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNegation.kt");
}
@Test
@TestMetadata("whenInNullComparison.kt")
public void testWhenInNullComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNullComparison.kt");
}
@Test
@TestMetadata("whenInPrimitiveToObjectComparison.kt")
public void testWhenInPrimitiveToObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInPrimitiveToObjectComparison.kt");
}
@Test
@TestMetadata("whenInZeroComparison.kt")
public void testWhenInZeroComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInZeroComparison.kt");
}
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {
@@ -595,6 +595,48 @@ public class K1WasmSteppingTestGenerated extends AbstractK1WasmSteppingTest {
runTest("compiler/testData/debug/stepping/whenExpr.kt");
}
@Test
@TestMetadata("whenInConjunction.kt")
public void testWhenInConjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInConjunction.kt");
}
@Test
@TestMetadata("whenInDisjunction.kt")
public void testWhenInDisjunction() throws Exception {
runTest("compiler/testData/debug/stepping/whenInDisjunction.kt");
}
@Test
@TestMetadata("whenInGeneralObjectComparison.kt")
public void testWhenInGeneralObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInGeneralObjectComparison.kt");
}
@Test
@TestMetadata("whenInNegation.kt")
public void testWhenInNegation() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNegation.kt");
}
@Test
@TestMetadata("whenInNullComparison.kt")
public void testWhenInNullComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInNullComparison.kt");
}
@Test
@TestMetadata("whenInPrimitiveToObjectComparison.kt")
public void testWhenInPrimitiveToObjectComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInPrimitiveToObjectComparison.kt");
}
@Test
@TestMetadata("whenInZeroComparison.kt")
public void testWhenInZeroComparison() throws Exception {
runTest("compiler/testData/debug/stepping/whenInZeroComparison.kt");
}
@Test
@TestMetadata("whenIsChecks.kt")
public void testWhenIsChecks() throws Exception {