diff --git a/generators/nativeInteropRuntime/NativeInteropRuntimeGenerator.kt b/generators/nativeInteropRuntime/NativeInteropRuntimeGenerator.kt index 0664652778f..f9b5063b4de 100644 --- a/generators/nativeInteropRuntime/NativeInteropRuntimeGenerator.kt +++ b/generators/nativeInteropRuntime/NativeInteropRuntimeGenerator.kt @@ -5,5 +5,51 @@ package org.jetbrains.kotlin.generators.native.interopRuntime -fun main() { +import java.io.File +import java.io.FileWriter + +fun FileWriter.generateHeader() { + appendLine(File("license/COPYRIGHT_HEADER.txt").readText()) + appendLine("package kotlinx.cinterop") + appendLine() + appendLine("//") + appendLine("// NOTE: THIS FILE IS AUTO-GENERATED by the generators/nativeInteropRuntime/NativeInteropRuntimeGenerator.kt") + appendLine("//") + appendLine() +} + +enum class PrimitiveInteropType { + Boolean, Byte, Short, Int, Long, UByte, UShort, UInt, ULong, Float, Double; +} + +fun FileWriter.generateAllocWithValue(type: PrimitiveInteropType) { + val typeName = type.name + + appendLine( + """ + /** + * Allocates variable with given value type and initializes it with given value. + */ + @Suppress("FINAL_UPPER_BOUND") + public fun NativePlacement.alloc(value: T): ${typeName}VarOf = + alloc<${typeName}VarOf> { this.value = value } + """.trimIndent() + ) +} + +fun generateUtils(targetDir: File) { + FileWriter(targetDir.resolve("_UtilsGenerated.kt")).use { writer -> + writer.generateHeader() + + for (type in PrimitiveInteropType.values()) { + writer.generateAllocWithValue(type) + writer.appendLine() + } + } +} + +fun main() { + val targetDir = File("kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop") + + generateUtils(targetDir) } diff --git a/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/_UtilsGenerated.kt b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/_UtilsGenerated.kt new file mode 100644 index 00000000000..afb18b23764 --- /dev/null +++ b/kotlin-native/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/_UtilsGenerated.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2010-2021 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 kotlinx.cinterop + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the generators/nativeInteropRuntime/NativeInteropRuntimeGenerator.kt +// + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): BooleanVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): ByteVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): ShortVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): IntVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): LongVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): UByteVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): UShortVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): UIntVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): ULongVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): FloatVarOf = + alloc> { this.value = value } + +/** + * Allocates variable with given value type and initializes it with given value. + */ +@Suppress("FINAL_UPPER_BOUND") +public fun NativePlacement.alloc(value: T): DoubleVarOf = + alloc> { this.value = value } + diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 717ac08a439..0a8bed88202 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -4705,6 +4705,10 @@ task interop_sourceCodeStruct(type: KonanLocalTest) { source = "codegen/intrinsics/interop_sourceCodeStruct.kt" } +task interop_alloc_value(type: KonanLocalTest) { + source = "runtime/interop/interop_alloc_value.kt" +} + standaloneTest("isExperimentalMM") { source = "codegen/intrinsics/isExperimentalMM.kt" flags = [ "-tr" ] diff --git a/kotlin-native/backend.native/tests/runtime/interop/interop_alloc_value.kt b/kotlin-native/backend.native/tests/runtime/interop/interop_alloc_value.kt new file mode 100644 index 00000000000..65380eb5004 --- /dev/null +++ b/kotlin-native/backend.native/tests/runtime/interop/interop_alloc_value.kt @@ -0,0 +1,96 @@ +package runtime.interop.interop_alloc_value + +import kotlinx.cinterop.* +import kotlin.test.* + +@Test +fun testBoolean() = memScoped { + assertEquals(true, alloc(true).value) + assertEquals(false, alloc(false).value) +} + +@Test +fun testByte() = memScoped { + assertEquals(Byte.MIN_VALUE, alloc(Byte.MIN_VALUE).value) + assertEquals(Byte.MAX_VALUE, alloc(Byte.MAX_VALUE).value) + assertEquals(0.toByte(), alloc(0.toByte()).value) + assertEquals(1.toByte(), alloc(1.toByte()).value) + assertEquals(1, alloc(1).value) +} + +@Test +fun testShort() = memScoped { + assertEquals(Short.MIN_VALUE, alloc(Short.MIN_VALUE).value) + assertEquals(Short.MAX_VALUE, alloc(Short.MAX_VALUE).value) + assertEquals(0.toShort(), alloc(0.toShort()).value) + assertEquals(2.toShort(), alloc(2.toShort()).value) + assertEquals(2, alloc(2).value) +} + +@Test +fun testInt() = memScoped { + assertEquals(Int.MIN_VALUE, alloc(Int.MIN_VALUE).value) + assertEquals(Int.MAX_VALUE, alloc(Int.MAX_VALUE).value) + assertEquals(0.toInt(), alloc(0.toInt()).value) + assertEquals(3.toInt(), alloc(3.toInt()).value) + assertEquals(3, alloc(3).value) +} + +@Test +fun testLong() = memScoped { + assertEquals(Long.MIN_VALUE, alloc(Long.MIN_VALUE).value) + assertEquals(Long.MAX_VALUE, alloc(Long.MAX_VALUE).value) + assertEquals(0L, alloc(0L).value) + assertEquals(4L, alloc(4L).value) + assertEquals(4, alloc(4).value) +} + +@Test +fun testUByte() = memScoped { + assertEquals(UByte.MIN_VALUE, alloc(UByte.MIN_VALUE).value) + assertEquals(UByte.MAX_VALUE, alloc(UByte.MAX_VALUE).value) + assertEquals(5.toUByte(), alloc(5.toUByte()).value) + assertEquals(5u, alloc(5u).value) +} + +@Test +fun testUShort() = memScoped { + assertEquals(UShort.MIN_VALUE, alloc(UShort.MIN_VALUE).value) + assertEquals(UShort.MAX_VALUE, alloc(UShort.MAX_VALUE).value) + assertEquals(6.toUShort(), alloc(6.toUShort()).value) + assertEquals(6u, alloc(6u).value) +} + +@Test +fun testUInt() = memScoped { + assertEquals(UInt.MIN_VALUE, alloc(UInt.MIN_VALUE).value) + assertEquals(UInt.MAX_VALUE, alloc(UInt.MAX_VALUE).value) + assertEquals(7.toUInt(), alloc(7.toUInt()).value) + assertEquals(7u, alloc(7u).value) +} + +@Test +fun testULong() = memScoped { + assertEquals(ULong.MIN_VALUE, alloc(ULong.MIN_VALUE).value) + assertEquals(ULong.MAX_VALUE, alloc(ULong.MAX_VALUE).value) + assertEquals(8uL, alloc(8uL).value) + assertEquals(8u, alloc(8u).value) +} + +@Test +fun testFloat() = memScoped { + assertEquals(Float.MIN_VALUE, alloc(Float.MIN_VALUE).value) + assertEquals(Float.MAX_VALUE, alloc(Float.MAX_VALUE).value) + assertEquals(0.0f, alloc(0.0f).value) + assertEquals(9.0f, alloc(9.0f).value) + assertEquals(9.0f, alloc(9.0f).value) +} + +@Test +fun testDouble() = memScoped { + assertEquals(Double.MIN_VALUE, alloc(Double.MIN_VALUE).value) + assertEquals(Double.MAX_VALUE, alloc(Double.MAX_VALUE).value) + assertEquals(0.0, alloc(0.0).value) + assertEquals(10.0, alloc(10.0).value) + assertEquals(10.0, alloc(10.0).value) +}