diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 2cb1b4a4efe..ac5ed4a19c8 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -12216,6 +12216,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt"); } + @TestMetadata("javaPrimitiveTypeIC.kt") + public void testJavaPrimitiveTypeIC() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/javaPrimitiveTypeIC.kt"); + } + @TestMetadata("jvmFieldInInlineClassCompanion.kt") public void testJvmFieldInInlineClassCompanion() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt"); @@ -13487,6 +13492,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType.kt"); } + @TestMetadata("javaPrimitiveType_UnitAndNothing.kt") + public void testJavaPrimitiveType_UnitAndNothing() throws Exception { + runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType_UnitAndNothing.kt"); + } + @TestMetadata("kt10131.kt") public void testKt10131() throws Exception { runTest("compiler/testData/codegen/box/intrinsics/kt10131.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/GetJavaPrimitiveType.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/GetJavaPrimitiveType.kt new file mode 100644 index 00000000000..14699b398b5 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/GetJavaPrimitiveType.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2020 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.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.codegen.* +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.ir.expressions.IrClassReference +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.expressions.IrGetClass +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.isTypeParameter +import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.org.objectweb.asm.Type + +object GetJavaPrimitiveType : IntrinsicMethod() { + + override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? { + val receiver = expression.extensionReceiver ?: return null + + val argumentType = + when (receiver) { + is IrGetClass -> receiver.argument.type + is IrClassReference -> receiver.classType + else -> return null + } + + if (argumentType.isTypeParameter()) return null + + val argumentAsmType = codegen.typeMapper.mapTypeAsDeclaration(argumentType) + + val isPrimitiveTypeOrWrapper = + argumentType.isPrimitiveType() || + argumentType.isNullablePrimitiveType() || + !argumentType.isInlineClassType() && argumentAsmType.isVoidOrPrimitiveWrapper() + + return when (receiver) { + is IrGetClass -> { + if (!isPrimitiveTypeOrWrapper) return null + + val argumentValue = receiver.argument.accept(codegen, data) + argumentValue.materialize() + AsmUtil.pop(codegen.mv, argumentValue.type) + putPrimitiveType(codegen, argumentAsmType) + + with(codegen) { expression.onStack } + } + + is IrClassReference -> { + if (!isPrimitiveTypeOrWrapper) { + codegen.mv.aconst(null) + } else { + putPrimitiveType(codegen, argumentAsmType) + } + + with(codegen) { expression.onStack } + } + + else -> + throw AssertionError("IrGetClass or IrClassReference expected: ${receiver.render()}") + } + } + + private fun putPrimitiveType(codegen: ExpressionCodegen, type: Type) { + codegen.mv.getstatic(AsmUtil.boxType(type).internalName, "TYPE", "Ljava/lang/Class;") + } + + private fun IrType.isInlineClassType(): Boolean { + return (classOrNull ?: return false).owner.isInline + } + + private fun Type.isVoidOrPrimitiveWrapper(): Boolean = + this == AsmTypes.VOID_WRAPPER_TYPE || AsmUtil.unboxPrimitiveTypeOrNull(this) != null +} \ No newline at end of file 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 0114c03e1b9..0909b3b85f5 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 @@ -44,6 +44,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) { listOf( Key(kotlinJvm, FqName("T"), "", emptyList()) to JavaClassProperty, Key(kotlinJvm, KotlinBuiltIns.FQ_NAMES.kClass.toSafe(), "", emptyList()) to GetJavaObjectType, + Key(kotlinJvm, KotlinBuiltIns.FQ_NAMES.kClass.toSafe(), "", emptyList()) to GetJavaPrimitiveType, Key( kotlinJvm, KotlinBuiltIns.FQ_NAMES.kClass.toSafe(), diff --git a/compiler/testData/codegen/box/inlineClasses/javaPrimitiveTypeIC.kt b/compiler/testData/codegen/box/inlineClasses/javaPrimitiveTypeIC.kt new file mode 100644 index 00000000000..bc6c0a4c28a --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/javaPrimitiveTypeIC.kt @@ -0,0 +1,34 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM +// WITH_RUNTIME +import kotlin.test.* + +inline class I(val x: Int) +inline class JLI(val x: java.lang.Integer) +inline class U(val x: Unit?) +inline class N(val x: Nothing?) + +val icUnit = U(Unit) +val icNull = N(null) + +val anyIcUnit: Any = icUnit +val anyIcNull: Any = icNull + +val z = I(42) +val jli = JLI(java.lang.Integer(42)) + +fun box(): String { + assertEquals(null, icUnit::class.javaPrimitiveType) + assertEquals(null, icNull::class.javaPrimitiveType) + assertEquals(null, anyIcUnit::class.javaPrimitiveType) + assertEquals(null, anyIcNull::class.javaPrimitiveType) + assertEquals(null, z::class.javaPrimitiveType) + assertEquals(null, jli::class.javaPrimitiveType) + + assertEquals(null, U::class.javaPrimitiveType) + assertEquals(null, N::class.javaPrimitiveType) + assertEquals(null, I::class.javaPrimitiveType) + assertEquals(null, JLI::class.javaPrimitiveType) + + return "OK" +} diff --git a/compiler/testData/codegen/box/intrinsics/javaPrimitiveType_UnitAndNothing.kt b/compiler/testData/codegen/box/intrinsics/javaPrimitiveType_UnitAndNothing.kt new file mode 100644 index 00000000000..fdf0724a762 --- /dev/null +++ b/compiler/testData/codegen/box/intrinsics/javaPrimitiveType_UnitAndNothing.kt @@ -0,0 +1,17 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM +// WITH_RUNTIME +import kotlin.test.* + +val pUnit = Unit +val pNUnit: Unit? = Unit + +fun box(): String { + assertEquals(null, pUnit::class.javaPrimitiveType) + assertEquals(null, pNUnit!!::class.javaPrimitiveType) + + assertEquals(null, Unit::class.javaPrimitiveType) + assertEquals(java.lang.Void.TYPE, Nothing::class.javaPrimitiveType) + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/intrinsics/javaPrimitiveType.kt b/compiler/testData/codegen/bytecodeText/intrinsics/javaPrimitiveType.kt index 93fc0b414ce..33ac3c27c19 100644 --- a/compiler/testData/codegen/bytecodeText/intrinsics/javaPrimitiveType.kt +++ b/compiler/testData/codegen/bytecodeText/intrinsics/javaPrimitiveType.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR class A { } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 37a9b22d996..f00aee24429 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13361,6 +13361,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt"); } + @TestMetadata("javaPrimitiveTypeIC.kt") + public void testJavaPrimitiveTypeIC() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/javaPrimitiveTypeIC.kt"); + } + @TestMetadata("jvmFieldInInlineClassCompanion.kt") public void testJvmFieldInInlineClassCompanion() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt"); @@ -14632,6 +14637,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType.kt"); } + @TestMetadata("javaPrimitiveType_UnitAndNothing.kt") + public void testJavaPrimitiveType_UnitAndNothing() throws Exception { + runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType_UnitAndNothing.kt"); + } + @TestMetadata("kt10131.kt") public void testKt10131() throws Exception { runTest("compiler/testData/codegen/box/intrinsics/kt10131.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index b0836e3415f..fef5386da40 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -13366,6 +13366,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt"); } + @TestMetadata("javaPrimitiveTypeIC.kt") + public void testJavaPrimitiveTypeIC() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/javaPrimitiveTypeIC.kt"); + } + @TestMetadata("jvmFieldInInlineClassCompanion.kt") public void testJvmFieldInInlineClassCompanion() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt"); @@ -14632,6 +14637,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType.kt"); } + @TestMetadata("javaPrimitiveType_UnitAndNothing.kt") + public void testJavaPrimitiveType_UnitAndNothing() throws Exception { + runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType_UnitAndNothing.kt"); + } + @TestMetadata("kt10131.kt") public void testKt10131() throws Exception { runTest("compiler/testData/codegen/box/intrinsics/kt10131.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 32a66555cff..2ef32804aa7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -12216,6 +12216,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt"); } + @TestMetadata("javaPrimitiveTypeIC.kt") + public void testJavaPrimitiveTypeIC() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/javaPrimitiveTypeIC.kt"); + } + @TestMetadata("jvmFieldInInlineClassCompanion.kt") public void testJvmFieldInInlineClassCompanion() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt"); @@ -13487,6 +13492,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType.kt"); } + @TestMetadata("javaPrimitiveType_UnitAndNothing.kt") + public void testJavaPrimitiveType_UnitAndNothing() throws Exception { + runTest("compiler/testData/codegen/box/intrinsics/javaPrimitiveType_UnitAndNothing.kt"); + } + @TestMetadata("kt10131.kt") public void testKt10131() throws Exception { runTest("compiler/testData/codegen/box/intrinsics/kt10131.kt");