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 <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
+19
-23
@@ -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<ClassDescriptor>) {
|
||||
private fun addUsedType(type: KotlinType, set: MutableSet<KotlinType>) {
|
||||
if (type.constructor.declarationDescriptor is TypeParameterDescriptor) return
|
||||
set.addIfNotNull(TypeUtils.getClassDescriptor(type))
|
||||
set.add(type)
|
||||
}
|
||||
|
||||
fun addUsedTypes(set: MutableSet<ClassDescriptor>) {
|
||||
fun addUsedTypes(set: MutableSet<KotlinType>) {
|
||||
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<ClassDescriptor>) {
|
||||
private fun defineUsedTypesImpl(scope: ExportedElementScope, set: MutableSet<KotlinType>) {
|
||||
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<ClassDescriptor>()
|
||||
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<KotlinType>()
|
||||
defineUsedTypesImpl(scope, usedTypes)
|
||||
val usedReferenceTypes = usedTypes.filter { isMappedToReference(it) }
|
||||
// Add nullable primitives, which are used in prototypes of "(*createNullable<PRIMITIVE_TYPE_NAME>)"
|
||||
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<String>()
|
||||
|
||||
@@ -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++"
|
||||
|
||||
@@ -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<ValueClass> = class Foo
|
||||
Foo<UsualClass> = class Foo
|
||||
@@ -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<T>
|
||||
|
||||
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<ValueClass>()
|
||||
val fooUsualClass = Foo<UsualClass>()
|
||||
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<ValueClass>) {
|
||||
println("Foo<ValueClass> = ${foo::class}")
|
||||
}
|
||||
fun fooFooUsual(foo: Foo<UsualClass>) {
|
||||
println("Foo<UsualClass> = ${foo::class}")
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
helloChar
|
||||
helloByte
|
||||
helloShort
|
||||
helloInt
|
||||
helloLong
|
||||
helloUByte
|
||||
helloUShort
|
||||
helloUInt
|
||||
helloULong
|
||||
helloFloat
|
||||
helloDouble
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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 <stdio.h>
|
||||
|
||||
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});
|
||||
}
|
||||
Reference in New Issue
Block a user