[KT-42830][Reverse C Interop] Add API to get value of boxed primitives
Merge-request: KT-MR-6836 Merged-by: Vladimir Sukharev <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
+25
-3
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
|
|
||||||
private enum class ScopeKind {
|
private enum class ScopeKind {
|
||||||
TOP,
|
TOP,
|
||||||
@@ -72,6 +71,9 @@ private val KotlinType.shortNameForPredefinedType
|
|||||||
private val KotlinType.createNullableNameForPredefinedType
|
private val KotlinType.createNullableNameForPredefinedType
|
||||||
get() = "createNullable${this.shortNameForPredefinedType}"
|
get() = "createNullable${this.shortNameForPredefinedType}"
|
||||||
|
|
||||||
|
private val KotlinType.createGetNonNullValueOfPredefinedType
|
||||||
|
get() = "getNonNullValueOf${this.shortNameForPredefinedType}"
|
||||||
|
|
||||||
internal val cKeywords = setOf(
|
internal val cKeywords = setOf(
|
||||||
// Actual C keywords.
|
// Actual C keywords.
|
||||||
"auto", "break", "case",
|
"auto", "break", "case",
|
||||||
@@ -532,12 +534,17 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
private var symbolTableOrNull: SymbolTable? = null
|
private var symbolTableOrNull: SymbolTable? = null
|
||||||
internal val symbolTable get() = symbolTableOrNull!!
|
internal val symbolTable get() = symbolTableOrNull!!
|
||||||
|
|
||||||
|
// Primitive built-ins and unsigned types
|
||||||
private val predefinedTypes = listOf(
|
private val predefinedTypes = listOf(
|
||||||
context.builtIns.byteType, context.builtIns.shortType,
|
context.builtIns.byteType, context.builtIns.shortType,
|
||||||
context.builtIns.intType, context.builtIns.longType,
|
context.builtIns.intType, context.builtIns.longType,
|
||||||
context.builtIns.floatType, context.builtIns.doubleType,
|
context.builtIns.floatType, context.builtIns.doubleType,
|
||||||
context.builtIns.charType, context.builtIns.booleanType,
|
context.builtIns.charType, context.builtIns.booleanType,
|
||||||
context.builtIns.unitType)
|
context.builtIns.unitType
|
||||||
|
) + UnsignedType.values().map {
|
||||||
|
// Unfortunately, `context.ir` and `context.irBuiltins` are not initialized, so `context.ir.symbols.ubyte`, etc, are unreachable.
|
||||||
|
context.builtIns.builtInsModule.findClassAcrossModuleDependencies(it.classId)!!.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): Map<ParameterDescriptor, String> {
|
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): Map<ParameterDescriptor, String> {
|
||||||
paramNamesRecorded.clear()
|
paramNamesRecorded.clear()
|
||||||
@@ -800,7 +807,7 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
defineUsedTypesImpl(scope, usedTypes)
|
defineUsedTypesImpl(scope, usedTypes)
|
||||||
val usedReferenceTypes = usedTypes.filter { isMappedToReference(it) }
|
val usedReferenceTypes = usedTypes.filter { isMappedToReference(it) }
|
||||||
// Add nullable primitives, which are used in prototypes of "(*createNullable<PRIMITIVE_TYPE_NAME>)"
|
// Add nullable primitives, which are used in prototypes of "(*createNullable<PRIMITIVE_TYPE_NAME>)"
|
||||||
val predefinedNullableTypes = predefinedTypes.map { it.makeNullable() }
|
val predefinedNullableTypes: List<KotlinType> = predefinedTypes.map { it.makeNullable() }
|
||||||
|
|
||||||
(predefinedNullableTypes + usedReferenceTypes)
|
(predefinedNullableTypes + usedReferenceTypes)
|
||||||
.map { translateType(it) }
|
.map { translateType(it) }
|
||||||
@@ -880,6 +887,8 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
val nullableIt = it.makeNullable()
|
val nullableIt = it.makeNullable()
|
||||||
val argument = if (!it.isUnit()) translateType(it) else "void"
|
val argument = if (!it.isUnit()) translateType(it) else "void"
|
||||||
output("${translateType(nullableIt)} (*${it.createNullableNameForPredefinedType})($argument);", 1)
|
output("${translateType(nullableIt)} (*${it.createNullableNameForPredefinedType})($argument);", 1)
|
||||||
|
if(!it.isUnit())
|
||||||
|
output("$argument (*${it.createGetNonNullValueOfPredefinedType})(${translateType(nullableIt)});", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
output("")
|
output("")
|
||||||
@@ -1009,6 +1018,16 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
output("KObjHeader* result = Kotlin_box${it.shortNameForPredefinedType}($argument result_holder.slot());", 1)
|
output("KObjHeader* result = Kotlin_box${it.shortNameForPredefinedType}($argument result_holder.slot());", 1)
|
||||||
output("return ${translateType(nullableIt)} { .pinned = CreateStablePointer(result) };", 1)
|
output("return ${translateType(nullableIt)} { .pinned = CreateStablePointer(result) };", 1)
|
||||||
output("}")
|
output("}")
|
||||||
|
|
||||||
|
if (!it.isUnit()) {
|
||||||
|
output("extern \"C\" ${translateType(it)} Kotlin_unbox${it.shortNameForPredefinedType}(KObjHeader*);")
|
||||||
|
output("static ${translateType(it)} ${it.createGetNonNullValueOfPredefinedType}Impl(${translateType(nullableIt)} value) {")
|
||||||
|
output("Kotlin_initRuntimeIfNeeded();", 1)
|
||||||
|
output("ScopedRunnableState stateGuard;", 1)
|
||||||
|
output("KObjHolder value_holder;", 1)
|
||||||
|
output("return Kotlin_unbox${it.shortNameForPredefinedType}(DerefStablePointer(value.pinned, value_holder.slot()));", 1)
|
||||||
|
output("}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
makeScopeDefinitions(top, DefinitionKind.C_SOURCE_DECLARATION, 0)
|
makeScopeDefinitions(top, DefinitionKind.C_SOURCE_DECLARATION, 0)
|
||||||
output("static ${prefix}_ExportedSymbols __konan_symbols = {")
|
output("static ${prefix}_ExportedSymbols __konan_symbols = {")
|
||||||
@@ -1017,6 +1036,9 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
|
|||||||
output(".IsInstance = IsInstanceImpl,", 1)
|
output(".IsInstance = IsInstanceImpl,", 1)
|
||||||
predefinedTypes.forEach {
|
predefinedTypes.forEach {
|
||||||
output(".${it.createNullableNameForPredefinedType} = ${it.createNullableNameForPredefinedType}Impl,", 1)
|
output(".${it.createNullableNameForPredefinedType} = ${it.createNullableNameForPredefinedType}Impl,", 1)
|
||||||
|
if (!it.isUnit()) {
|
||||||
|
output(".${it.createGetNonNullValueOfPredefinedType} = ${it.createGetNonNullValueOfPredefinedType}Impl,", 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeScopeDefinitions(top, DefinitionKind.C_SOURCE_STRUCT, 1)
|
makeScopeDefinitions(top, DefinitionKind.C_SOURCE_STRUCT, 1)
|
||||||
|
|||||||
@@ -5236,6 +5236,13 @@ for (i in 0..2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dynamicTest("kt42830") {
|
||||||
|
disabled = (project.testTarget == 'wasm32') // wasm doesn't support -produce dynamic
|
||||||
|
source = "produce_dynamic/kt-42830/box_unbox.kt"
|
||||||
|
cSource = "$projectDir/produce_dynamic/kt-42830/main.c"
|
||||||
|
useGoldenData = true
|
||||||
|
}
|
||||||
|
|
||||||
dynamicTest("produce_dynamic_unhandledException") {
|
dynamicTest("produce_dynamic_unhandledException") {
|
||||||
disabled = (project.testTarget == 'wasm32') || // Uses exceptions + dynamic is unsupported for wasm.
|
disabled = (project.testTarget == 'wasm32') || // Uses exceptions + dynamic is unsupported for wasm.
|
||||||
(cacheTesting != null) // Disabled due to KT-47828.
|
(cacheTesting != null) // Disabled due to KT-47828.
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
true
|
||||||
|
true
|
||||||
|
true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-128
|
||||||
|
-128
|
||||||
|
-128
|
||||||
|
-32768
|
||||||
|
-32768
|
||||||
|
-32768
|
||||||
|
-2147483648
|
||||||
|
-2147483648
|
||||||
|
-2147483648
|
||||||
|
-9223372036854775808
|
||||||
|
-9223372036854775808
|
||||||
|
-9223372036854775808
|
||||||
|
3.4028235E38
|
||||||
|
3.4028235E38
|
||||||
|
3.4028235E38
|
||||||
|
1.7976931348623157E308
|
||||||
|
1.7976931348623157E308
|
||||||
|
1.7976931348623157E308
|
||||||
|
255
|
||||||
|
255
|
||||||
|
255
|
||||||
|
65535
|
||||||
|
65535
|
||||||
|
65535
|
||||||
|
4294967295
|
||||||
|
4294967295
|
||||||
|
4294967295
|
||||||
|
18446744073709551615
|
||||||
|
18446744073709551615
|
||||||
|
18446744073709551615
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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 printAny(v: Any?) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printBoolean(v: Boolean) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printChar(v: Char) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printByte(v: Byte) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printShort(v: Short) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printInt(v: Int) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printLong(v: Long) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printFloat(v: Float) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printDouble(v: Double) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printUByte(v: UByte) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printUShort(v: UShort) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printUInt(v: UInt) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
|
fun printULong(v: ULong) {
|
||||||
|
println(v)
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
#define TEST_TYPE_VAL(TYPE_C, TYPE, VAL) \
|
||||||
|
TYPE_C primitive##TYPE = VAL; \
|
||||||
|
__ kotlin.root.print##TYPE (primitive##TYPE); \
|
||||||
|
T_(kotlin_##TYPE) nullable##TYPE = __ createNullable##TYPE (primitive##TYPE); \
|
||||||
|
T_(kotlin_Any) any##TYPE = { .pinned = nullable##TYPE.pinned }; \
|
||||||
|
__ kotlin.root.printAny (any##TYPE); \
|
||||||
|
TYPE_C unboxed##TYPE = __ getNonNullValueOf##TYPE (nullable##TYPE); \
|
||||||
|
__ kotlin.root.print##TYPE (unboxed##TYPE);
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
TEST_TYPE_VAL(bool, Boolean, true);
|
||||||
|
TEST_TYPE_VAL(uint16_t, Char, UINT16_MAX);
|
||||||
|
TEST_TYPE_VAL(int8_t, Byte, INT8_MIN);
|
||||||
|
TEST_TYPE_VAL(int16_t, Short, INT16_MIN);
|
||||||
|
TEST_TYPE_VAL(int32_t, Int, INT32_MIN);
|
||||||
|
TEST_TYPE_VAL(int64_t, Long, INT64_MIN);
|
||||||
|
TEST_TYPE_VAL(float, Float, FLT_MAX);
|
||||||
|
TEST_TYPE_VAL(double, Double, DBL_MAX);
|
||||||
|
TEST_TYPE_VAL(uint8_t, UByte, UINT8_MAX);
|
||||||
|
TEST_TYPE_VAL(uint16_t, UShort, UINT16_MAX);
|
||||||
|
TEST_TYPE_VAL(uint32_t, UInt, UINT32_MAX);
|
||||||
|
TEST_TYPE_VAL(uint64_t, ULong, UINT64_MAX);
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ external fun getCachedLongBox(value: Long): Long?
|
|||||||
@GCUnsafeCall("inLongBoxCache")
|
@GCUnsafeCall("inLongBoxCache")
|
||||||
external fun inLongBoxCache(value: Long): Boolean
|
external fun inLongBoxCache(value: Long): Boolean
|
||||||
|
|
||||||
// TODO: functions below are used for ObjCExport, move and rename them correspondigly.
|
// TODO: functions below are used for ObjCExport and CAdapterGenerator, move and rename them correspondigly.
|
||||||
|
|
||||||
@ExportForCppRuntime("Kotlin_boxBoolean")
|
@ExportForCppRuntime("Kotlin_boxBoolean")
|
||||||
fun boxBoolean(value: Boolean): Boolean? = value
|
fun boxBoolean(value: Boolean): Boolean? = value
|
||||||
@@ -85,3 +85,45 @@ fun boxDouble(value: Double): Double? = value
|
|||||||
|
|
||||||
@ExportForCppRuntime("Kotlin_boxUnit")
|
@ExportForCppRuntime("Kotlin_boxUnit")
|
||||||
internal fun Kotlin_boxUnit(): Unit? = Unit
|
internal fun Kotlin_boxUnit(): Unit? = Unit
|
||||||
|
|
||||||
|
// Unbox fuctions
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxBoolean")
|
||||||
|
fun unboxBoolean(value: Boolean?): Boolean = value!!
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxChar")
|
||||||
|
fun unboxChar(value: Char?): Char = value!!
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxByte")
|
||||||
|
fun unboxByte(value: Byte?): Byte = value!!
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxShort")
|
||||||
|
fun unboxShort(value: Short?): Short = value!!
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxInt")
|
||||||
|
fun unboxInt(value: Int?): Int = value!!
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxLong")
|
||||||
|
fun unboxLong(value: Long?): Long = value!!
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxUByte")
|
||||||
|
fun unboxUByte(value: UByte?): UByte = value!!
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxUShort")
|
||||||
|
fun unboxUShort(value: UShort?): UShort = value!!
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxUInt")
|
||||||
|
fun unboxUInt(value: UInt?): UInt = value!!
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxULong")
|
||||||
|
fun unboxULong(value: ULong?): ULong = value!!
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxFloat")
|
||||||
|
fun unboxFloat(value: Float?): Float = value!!
|
||||||
|
|
||||||
|
@ExportForCppRuntime("Kotlin_unboxDouble")
|
||||||
|
fun unboxDouble(value: Double?): Double = value!!
|
||||||
|
|||||||
Reference in New Issue
Block a user