From f8f01941a8c664305cb15ba5786d76959ab3e865 Mon Sep 17 00:00:00 2001 From: Vladimir Sukharev Date: Wed, 6 Jul 2022 11:02:16 +0000 Subject: [PATCH] Generate typedef wrappers for nullable inline classes and method args (KT-36878, KT-39015, KT-39496) Merge-request: KT-MR-6597 Merged-by: Vladimir Sukharev --- .../kotlin/backend/konan/CAdapterGenerator.kt | 42 ++++++++-------- .../backend.native/tests/build.gradle | 21 ++++++++ .../produce_dynamic/kt-36878/hello-main.out | 6 +++ .../tests/produce_dynamic/kt-36878/hello.kt | 36 ++++++++++++++ .../tests/produce_dynamic/kt-36878/main.c | 23 +++++++++ .../produce_dynamic/kt-39015/hello-main.out | 1 + .../tests/produce_dynamic/kt-39015/hello.kt | 10 ++++ .../tests/produce_dynamic/kt-39015/main.c | 15 ++++++ .../produce_dynamic/kt-39496/hello-main.out | 11 +++++ .../tests/produce_dynamic/kt-39496/hello.kt | 48 +++++++++++++++++++ .../tests/produce_dynamic/kt-39496/main.c | 23 +++++++++ 11 files changed, 213 insertions(+), 23 deletions(-) create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello-main.out create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello.kt create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-36878/main.c create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello-main.out create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello.kt create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-39015/main.c create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello-main.out create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello.kt create mode 100644 kotlin-native/backend.native/tests/produce_dynamic/kt-39496/main.c diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt index 9ccb6bed94f..caeb51c79fe 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt @@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.annotations.* import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.makeNullable @@ -479,12 +478,12 @@ private class ExportedElement(val kind: ElementKind, return builder.toString() } - private fun addUsedType(type: KotlinType, set: MutableSet) { + private fun addUsedType(type: KotlinType, set: MutableSet) { if (type.constructor.declarationDescriptor is TypeParameterDescriptor) return - set.addIfNotNull(TypeUtils.getClassDescriptor(type)) + set.add(type) } - fun addUsedTypes(set: MutableSet) { + fun addUsedTypes(set: MutableSet) { val descriptor = declaration when (descriptor) { is FunctionDescriptor -> { @@ -497,7 +496,7 @@ private class ExportedElement(val kind: ElementKind, addUsedType(original.correspondingProperty.type, set) } is ClassDescriptor -> { - set += descriptor + set += descriptor.defaultType } } } @@ -787,7 +786,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi if (kind == DefinitionKind.C_SOURCE_STRUCT) output("},", indent) } - private fun defineUsedTypesImpl(scope: ExportedElementScope, set: MutableSet) { + private fun defineUsedTypesImpl(scope: ExportedElementScope, set: MutableSet) { scope.elements.forEach { it.addUsedTypes(set) } @@ -797,23 +796,20 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi } private fun defineUsedTypes(scope: ExportedElementScope, indent: Int) { - val set = mutableSetOf() - defineUsedTypesImpl(scope, set) - // Add nullable primitives. - predefinedTypes.forEach { - val nullableIt = it.makeNullable() - output("typedef struct {", indent) - output("${prefix}_KNativePtr pinned;", indent + 1) - output("} ${translateType(nullableIt)};", indent) - } - set.forEach { - val type = it.defaultType - if (isMappedToReference(type) && !it.isInlined()) { - output("typedef struct {", indent) - output("${prefix}_KNativePtr pinned;", indent + 1) - output("} ${translateType(type)};", indent) - } - } + val usedTypes = mutableSetOf() + defineUsedTypesImpl(scope, usedTypes) + val usedReferenceTypes = usedTypes.filter { isMappedToReference(it) } + // Add nullable primitives, which are used in prototypes of "(*createNullable)" + val predefinedNullableTypes = predefinedTypes.map { it.makeNullable() } + + (predefinedNullableTypes + usedReferenceTypes) + .map { translateType(it) } + .toSet() + .forEach { + output("typedef struct {", indent) + output("${prefix}_KNativePtr pinned;", indent + 1) + output("} $it;", indent) + } } val exportedSymbols = mutableListOf() diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 46dec15837c..87de7f67201 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -5181,6 +5181,27 @@ dynamicTest("kt36639") { useGoldenData = true } +dynamicTest("kt36878") { + disabled = (project.testTarget == 'wasm32') // wasm doesn't support -produce dynamic + source = "produce_dynamic/kt-36878/hello.kt" + cSource = "$projectDir/produce_dynamic/kt-36878/main.c" + useGoldenData = true +} + +dynamicTest("kt39015") { + disabled = (project.testTarget == 'wasm32') // wasm doesn't support -produce dynamic + source = "produce_dynamic/kt-39015/hello.kt" + cSource = "$projectDir/produce_dynamic/kt-39015/main.c" + useGoldenData = true +} + +dynamicTest("kt39496") { + disabled = (project.testTarget == 'wasm32') // wasm doesn't support -produce dynamic + source = "produce_dynamic/kt-39496/hello.kt" + cSource = "$projectDir/produce_dynamic/kt-39496/main.c" + useGoldenData = true +} + for (i in 0..2) { dynamicTest("kt42796_$i") { clangTool = "clang++" diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello-main.out b/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello-main.out new file mode 100644 index 00000000000..b280057b8f1 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello-main.out @@ -0,0 +1,6 @@ +ValueClass? = ValueClass(number=153) +UsualClass? = 128 +UByteArray = UByteArray(storage=[64, -128]): 64, 128 +UIntArray? = UIntArray(storage=[64, 128]): 64, 128 +Foo = class Foo +Foo = class Foo diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello.kt b/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello.kt new file mode 100644 index 00000000000..336218d0486 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/hello.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2022 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. + */ + +value class ValueClass(val number: Int) {} +class UsualClass(val number: UByte) {} +class Foo + +object ObjectForExample { + val nullableVal: ValueClass? = ValueClass(153) + val usual: UsualClass = UsualClass(128.toUByte()) + val uByteArray: UByteArray = ubyteArrayOf(0x40.toUByte(), 0x80.toUByte()) + val uIntArray: UIntArray = intArrayOf(0x40, 0x80).toUIntArray() + val fooValueClass = Foo() + val fooUsualClass = Foo() + fun fooValue(foo: ValueClass?) { + println("ValueClass? = $foo") + } + fun fooUsual(foo: UsualClass?) { + println("UsualClass? = ${foo?.number}") + } + fun fooUByteArray(foo: UByteArray) { + println("UByteArray = $foo: ${foo.joinToString()}") + + } + fun fooUIntArrayNullable(foo: UIntArray?) { + println("UIntArray? = $foo: ${foo?.joinToString()}") + } + fun fooFooValue(foo: Foo) { + println("Foo = ${foo::class}") + } + fun fooFooUsual(foo: Foo) { + println("Foo = ${foo::class}") + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/main.c b/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/main.c new file mode 100644 index 00000000000..a71a4873a8a --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-36878/main.c @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2022 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. + */ +#include "testlib_api.h" +#define __ testlib_symbols()-> +#define T_(x) testlib_kref_ ## x + +int main(int argc, char** argv) { + T_(ObjectForExample) instance = __ kotlin.root.ObjectForExample._instance (); + T_(ValueClass) value = __ kotlin.root.ObjectForExample.get_nullableVal (instance); + T_(UsualClass) usual = __ kotlin.root.ObjectForExample.get_usual (instance); + T_(kotlin_ByteArray) uByteArray = __ kotlin.root.ObjectForExample.get_uByteArray (instance); + T_(kotlin_IntArray) uIntArray = __ kotlin.root.ObjectForExample.get_uIntArray (instance); + T_(Foo) fooValueClass = __ kotlin.root.ObjectForExample.get_fooValueClass (instance); + T_(Foo) fooUsualClass = __ kotlin.root.ObjectForExample.get_fooValueClass (instance); + __ kotlin.root.ObjectForExample.fooValue (instance, value); + __ kotlin.root.ObjectForExample.fooUsual (instance, usual); + __ kotlin.root.ObjectForExample.fooUByteArray (instance, uByteArray); + __ kotlin.root.ObjectForExample.fooUIntArrayNullable (instance, uIntArray); + __ kotlin.root.ObjectForExample.fooFooValue (instance, fooValueClass); + __ kotlin.root.ObjectForExample.fooFooUsual (instance, fooUsualClass); +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello-main.out b/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello-main.out new file mode 100644 index 00000000000..573541ac970 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello-main.out @@ -0,0 +1 @@ +0 diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello.kt b/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello.kt new file mode 100644 index 00000000000..7684511f370 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/hello.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2022 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. + */ + +inline class Example(val number: Int) {} + +object ObjectForExample { + val example: Example? = null +} diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/main.c b/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/main.c new file mode 100644 index 00000000000..cbcc61788f2 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-39015/main.c @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2022 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. + */ +#include "testlib_api.h" +#define __ testlib_symbols()-> +#define T_(x) testlib_kref_ ## x + +#include + +int main(int argc, char** argv) { + T_(ObjectForExample) instance = __ kotlin.root.ObjectForExample._instance (); + T_(Example) value = __ kotlin.root.ObjectForExample.get_example (instance); + printf("%x\n", value.pinned); +} diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello-main.out b/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello-main.out new file mode 100644 index 00000000000..49bc8f9c6d2 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello-main.out @@ -0,0 +1,11 @@ +helloChar +helloByte +helloShort +helloInt +helloLong +helloUByte +helloUShort +helloUInt +helloULong +helloFloat +helloDouble diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello.kt b/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello.kt new file mode 100644 index 00000000000..dbdbf44ec06 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/hello.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2022 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. + */ + +fun helloChar(value: Char?) { + println("helloChar") +} + +fun helloByte(value: Byte?) { + println("helloByte") +} + +fun helloShort(value: Short?) { + println("helloShort") +} + +fun helloInt(value: Int?) { + println("helloInt") +} + +fun helloLong(value: Long?) { + println("helloLong") +} + +fun helloUByte(value: UByte?) { + println("helloUByte") +} + +fun helloUShort(value: UShort?) { + println("helloUShort") +} + +fun helloUInt(value: UInt?) { + println("helloUInt") +} + +fun helloULong(value: ULong?) { + println("helloULong") +} + +fun helloFloat(value: Float?) { + println("helloFloat") +} + +fun helloDouble(value: Double?) { + println("helloDouble") +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/main.c b/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/main.c new file mode 100644 index 00000000000..9b661fbd3a9 --- /dev/null +++ b/kotlin-native/backend.native/tests/produce_dynamic/kt-39496/main.c @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2022 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. + */ +#include "testlib_api.h" +#define __ testlib_symbols()-> +#define T_(x) testlib_kref_ ## x + +#include + +int main(int argc, char** argv) { + __ kotlin.root.helloChar ((T_(kotlin_Char)) {NULL}); + __ kotlin.root.helloByte ((T_(kotlin_Byte)) {NULL}); + __ kotlin.root.helloShort ((T_(kotlin_Short)) {NULL}); + __ kotlin.root.helloInt ((T_(kotlin_Int)) {NULL}); + __ kotlin.root.helloLong ((T_(kotlin_Long)) {NULL}); + __ kotlin.root.helloUByte ((T_(kotlin_UByte)) {NULL}); + __ kotlin.root.helloUShort ((T_(kotlin_UShort)) {NULL}); + __ kotlin.root.helloUInt ((T_(kotlin_UInt)) {NULL}); + __ kotlin.root.helloULong ((T_(kotlin_ULong)) {NULL}); + __ kotlin.root.helloFloat ((T_(kotlin_Float)) {NULL}); + __ kotlin.root.helloDouble ((T_(kotlin_Double)) {NULL}); +}