diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt index 62bd947a10d..e9ebffb5f94 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FileInitializersLowering.kt @@ -41,6 +41,10 @@ internal val IrFunction.isFileInitializer: Boolean || origin == DECLARATION_ORIGIN_FILE_THREAD_LOCAL_INITIALIZER || origin == DECLARATION_ORIGIN_FILE_STANDALONE_THREAD_LOCAL_INITIALIZER +internal val IrFunction.isModuleInitializer: Boolean + get() = origin == DECLARATION_ORIGIN_MODULE_GLOBAL_INITIALIZER + || origin == DECLARATION_ORIGIN_MODULE_THREAD_LOCAL_INITIALIZER + internal fun IrBuilderWithScope.irCallFileInitializer(initializer: IrFunctionSymbol) = irCall(initializer) @@ -82,16 +86,18 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass ) else null - irFile.simpleFunctions().forEach { - val body = it.body ?: return@forEach - val statements = (body as IrBlockBody).statements - context.createIrBuilder(it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).run { - // The order of calling initializers: first global, then thread-local. - // It is ok for a thread local top level property to reference a global, but not vice versa. - threadLocalInitFunction?.let { statements.add(0, irCallFileInitializer(it.symbol)) } - globalInitFunction?.let { statements.add(0, irCallFileInitializer(it.symbol)) } - } - } + irFile.simpleFunctions() + .filterNot { it.isModuleInitializer } + .forEach { + val body = it.body ?: return@forEach + val statements = (body as IrBlockBody).statements + context.createIrBuilder(it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).run { + // The order of calling initializers: first global, then thread-local. + // It is ok for a thread local top level property to reference a global, but not vice versa. + threadLocalInitFunction?.let { statements.add(0, irCallFileInitializer(it.symbol)) } + globalInitFunction?.let { statements.add(0, irCallFileInitializer(it.symbol)) } + } + } } private fun buildInitFileFunction(irFile: IrFile, name: String, origin: IrDeclarationOrigin) = context.irFactory.buildFun { diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 6ddb025be8c..98db1c852a6 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -1523,6 +1523,12 @@ standaloneTest("initializers_eagerInitializationThreadLocal2") { source = "codegen/initializers/eagerInitializationThreadLocal2.kt" } +standaloneTest("initializers_testInfrastructure") { + enabled = project.globalTestArgs.contains('-Xir-property-lazy-initialization=enable') || isExperimentalMM + source = "codegen/initializers/testInfrastructure.kt" + flags = ["-tr"] +} + standaloneTest("initializers_workers1") { expectedFail = (project.testTarget == 'wasm32') // Workers are not supported source = "codegen/initializers/workers1.kt" diff --git a/kotlin-native/backend.native/tests/codegen/initializers/testInfrastructure.kt b/kotlin-native/backend.native/tests/codegen/initializers/testInfrastructure.kt new file mode 100644 index 00000000000..927b7a60f59 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/initializers/testInfrastructure.kt @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// FILE: lib.kt +var z1 = false +var z2 = false +var t1 = false +var t2 = false + +// FILE: lib2.kt +import kotlin.test.* + +private val x = foo() + +private fun foo(): Int { + z1 = true + return 42 +} + +@Test +fun test1() { + t1 = true + assertTrue(z1) + assertTrue(t2 || !z2) +} + +// FILE: main.kt +import kotlin.test.* + +private val x = foo() + +private fun foo(): Int { + z2 = true + return 42 +} + +@Test +fun test2() { + t2 = true + assertTrue(z2) + assertTrue(t1 || !z1) +}