diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt index 576f6c53218..dbf08c79efb 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt @@ -30,9 +30,29 @@ import org.jetbrains.kotlin.types.isNullable import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberOrNullableType import org.jetbrains.kotlin.types.typeUtil.upperBoundedByPrimitiveNumberOrNullableType import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +class ExplicitEquals : IntrinsicMethod() { + override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? { + val (a, b) = expression.receiverAndArgs() + + // TODO use specialized boxed type - this might require types like 'java.lang.Integer' in IR + a.accept(codegen, data).coerce(AsmTypes.OBJECT_TYPE, codegen.context.irBuiltIns.anyNType).materialize() + b.accept(codegen, data).coerce(AsmTypes.OBJECT_TYPE, codegen.context.irBuiltIns.anyNType).materialize() + codegen.mv.visitMethodInsn( + Opcodes.INVOKEVIRTUAL, + AsmTypes.OBJECT_TYPE.internalName, + "equals", + Type.getMethodDescriptor(Type.BOOLEAN_TYPE, AsmTypes.OBJECT_TYPE), + false + ) + + return MaterialValue(codegen, Type.BOOLEAN_TYPE, codegen.context.irBuiltIns.booleanType) + } +} + class Equals(val operator: IElementType) : IntrinsicMethod() { private class BooleanConstantFalseCheck(val value: PromisedValue) : BooleanValue(value.codegen) { override fun materialize() = value.discard().let { mv.iconst(0) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt index 82a7ad98d84..a21b7fd6c47 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -103,7 +103,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { unaryFunForPrimitives("inc", INC) + unaryFunForPrimitives("dec", DEC) + unaryFunForPrimitives("hashCode", HashCode) + - binaryFunForPrimitives("equals", EQUALS, irBuiltIns.anyClass) + + binaryFunForPrimitives("equals", EXPLICIT_EQUALS, irBuiltIns.anyClass) + binaryFunForPrimitivesAcrossPrimitives("rangeTo", RangeTo) + binaryOp("plus", IADD) + binaryOp("minus", ISUB) + @@ -193,7 +193,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { private val INC = Increment(1) private val DEC = Increment(-1) - private val EQUALS = Equals(KtTokens.EQEQ) + private val EXPLICIT_EQUALS = ExplicitEquals() private fun IrFunctionSymbol.toKey(): Key? { val parent = owner.parent diff --git a/compiler/testData/codegen/box/platformTypes/primitives/equalsNull.kt b/compiler/testData/codegen/box/platformTypes/primitives/equalsNull.kt index 95866d77b19..f43b8c96106 100644 --- a/compiler/testData/codegen/box/platformTypes/primitives/equalsNull.kt +++ b/compiler/testData/codegen/box/platformTypes/primitives/equalsNull.kt @@ -1,10 +1,7 @@ // IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME -// FILE: equalsNull_lv12.kt - -// IGNORE_BACKEND: JVM_IR -// ^ TODO: fix intrinsic for 'equals' for boxed primitives +// FILE: equalsNull.kt import kotlin.test.* diff --git a/compiler/testData/codegen/box/platformTypes/primitives/equalsNull_withExplicitFlag.kt b/compiler/testData/codegen/box/platformTypes/primitives/equalsNull_withExplicitFlag.kt index 536ceb5d142..8a5a423771e 100644 --- a/compiler/testData/codegen/box/platformTypes/primitives/equalsNull_withExplicitFlag.kt +++ b/compiler/testData/codegen/box/platformTypes/primitives/equalsNull_withExplicitFlag.kt @@ -4,8 +4,7 @@ // WITH_RUNTIME // FILE: equalsNull_withExplicitFlag.kt -// Should be ignored on JVM IR. -// ^ TODO: fix intrinsic for 'equals' for boxed primitives +// IGNORE_BACKEND: JVM_IR // JVM_IR supports behavior since Kotlin 1.3, // and '-Xno-exception-on-explicit-equals-for-boxed-null' is a fallback flag introduced in 1.2.