From e324c9b3fb6ba7e9659dde6aaa23681ccd971182 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Wed, 16 Jun 2021 06:39:51 +0000 Subject: [PATCH] Generate initRuntimeIfNeeded() at the beginning of staticCFunction #KT-44283 Fixed --- .../backend/konan/llvm/CodeGenerator.kt | 11 +++++++- .../backend.native/tests/build.gradle | 12 +++++++++ .../tests/interop/kt44283/kt44283.def | 25 +++++++++++++++++++ .../tests/interop/kt44283/main.kt | 21 ++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 kotlin-native/backend.native/tests/interop/kt44283/kt44283.def create mode 100644 kotlin-native/backend.native/tests/interop/kt44283/main.kt diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index ba654468515..a779f10bf23 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -128,13 +128,22 @@ internal inline fun generateFunction(codegen: CodeGenerator, code: FunctionGenerationContext.(FunctionGenerationContext) -> R) { val llvmFunction = codegen.llvmFunction(function) + val isCToKotlinBridge = function.origin == CBridgeOrigin.C_TO_KOTLIN_BRIDGE + val functionGenerationContext = FunctionGenerationContext( llvmFunction, codegen, startLocation, endLocation, - switchToRunnable = function.origin == CBridgeOrigin.C_TO_KOTLIN_BRIDGE, + switchToRunnable = isCToKotlinBridge, function) + + if (isCToKotlinBridge) { + // Enable initRuntimeIfNeeded for legacy MM too: + functionGenerationContext.needsRuntimeInit = true + // This fixes https://youtrack.jetbrains.com/issue/KT-44283. + } + try { generateFunctionBody(functionGenerationContext, code) } finally { diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 8ccf2d2ed28..873e6992a8a 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -3806,6 +3806,10 @@ createInterop("kt43265") { it.defFile 'interop/kt43265/kt43265.def' } +createInterop("kt44283") { + it.defFile 'interop/kt44283/kt44283.def' +} + createInterop("kt43502") { it.defFile 'interop/kt43502/kt43502.def' it.headers "$projectDir/interop/kt43502/kt43502.h" @@ -4190,6 +4194,14 @@ interopTest("interop_kt43265") { source = "interop/kt43265/usage.kt" } +interopTest("interop_kt44283") { + disabled = (project.testTarget == 'wasm32') || // No interop for wasm yet. + project.globalTestArgs.contains('-opt') // Incompatible with -g. + flags = ['-g'] + interop = 'kt44283' + source = "interop/kt44283/main.kt" +} + dynamicTest("interop_kt43502") { disabled = (project.target.name != project.hostName) interop = "kt43502" diff --git a/kotlin-native/backend.native/tests/interop/kt44283/kt44283.def b/kotlin-native/backend.native/tests/interop/kt44283/kt44283.def new file mode 100644 index 00000000000..bee0eacc109 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/kt44283/kt44283.def @@ -0,0 +1,25 @@ +--- +#include +#include + +typedef struct { + int d; +} TestStruct; + +typedef struct { + void (*f)(TestStruct data); +} ThreadData; + +void *dispatch(void *rawArg) { + ThreadData *arg = rawArg; + arg->f((TestStruct) {.d = 1}); + return NULL; +} + +void invokeFromThread(void (*f)(TestStruct data)) { + pthread_t thread_id; + ThreadData *threadData = malloc(sizeof(ThreadData)); + threadData->f = f; + pthread_create(&thread_id, NULL, dispatch, (void *) threadData); + pthread_join(thread_id, NULL); +} diff --git a/kotlin-native/backend.native/tests/interop/kt44283/main.kt b/kotlin-native/backend.native/tests/interop/kt44283/main.kt new file mode 100644 index 00000000000..77b15b110e6 --- /dev/null +++ b/kotlin-native/backend.native/tests/interop/kt44283/main.kt @@ -0,0 +1,21 @@ +import kotlinx.cinterop.* +import kt44283.* +import kotlin.native.concurrent.AtomicInt +import kotlin.test.* + +val callbackCounter = AtomicInt(0) + +fun main() { + val func = staticCFunction, Unit> { + kotlin.native.internal.GC.collect() // Helps to ensure that "runtime" is already initialized. + + memScoped { + println("Hello, Kotlin/Native! ${it.ptr.pointed.d}") + } + callbackCounter.increment() + } + + assertEquals(0, callbackCounter.value) + invokeFromThread(func.reinterpret()) + assertEquals(1, callbackCounter.value) +} \ No newline at end of file