diff --git a/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt b/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt index 70472530897..1e2d9e70aaf 100644 --- a/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt +++ b/compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt @@ -1,7 +1,5 @@ // IGNORE_BACKEND: WASM // WASM_MUTE_REASON: IGNORED_IN_JS -// KT-59058 -// IGNORE_BACKEND: NATIVE var global = "A" class C { diff --git a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionEvaluationOrder.kt b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionEvaluationOrder.kt index fe60a68d0b6..a7feb912a72 100644 --- a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionEvaluationOrder.kt +++ b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionEvaluationOrder.kt @@ -1,7 +1,5 @@ // IGNORE_BACKEND: WASM // WASM_MUTE_REASON: NESTED_OBJECT_INIT -// KT-59058 -// IGNORE_BACKEND: NATIVE // WITH_STDLIB // WITH_COROUTINES import helpers.* diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StaticInitializersLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StaticInitializersLowering.kt index 0a3ab71bd65..cde42cb91df 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StaticInitializersLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StaticInitializersLowering.kt @@ -19,10 +19,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET -import org.jetbrains.kotlin.ir.util.hasAnnotation -import org.jetbrains.kotlin.ir.util.hasNonConstInitializer -import org.jetbrains.kotlin.ir.util.simpleFunctions +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -96,18 +93,22 @@ internal class StaticInitializersLowering(val context: Context) : FileLoweringPa ) else null + fun IrFunction.addInitializersCall() { + val body = body ?: return + val statements = (body as IrBlockBody).statements + context.createIrBuilder(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)) } + } + } + container.simpleFunctions() + .filter { it.dispatchReceiverParameter == null } .filterNot { it.origin == DECLARATION_ORIGIN_ENTRY_POINT } - .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)) } - } - } + .forEach { it.addInitializersCall() } + (container as? IrClass)?.constructors?.forEach { it.addInitializersCall() } } private fun buildInitFileFunction(container: IrDeclarationContainer, name: String, origin: IrDeclarationOrigin) = context.irFactory.buildFun { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/StaticInitializersOptimization.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/StaticInitializersOptimization.kt index 41efad84037..a1c833e247d 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/StaticInitializersOptimization.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/StaticInitializersOptimization.kt @@ -14,6 +14,8 @@ import org.jetbrains.kotlin.backend.konan.DirectedGraphCondensationBuilder import org.jetbrains.kotlin.backend.konan.DirectedGraphMultiNode import org.jetbrains.kotlin.backend.konan.ir.actualCallee import org.jetbrains.kotlin.backend.konan.ir.isVirtualCall +import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType +import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType import org.jetbrains.kotlin.backend.konan.logMultiple import org.jetbrains.kotlin.backend.konan.lower.* import org.jetbrains.kotlin.ir.IrElement @@ -542,6 +544,23 @@ internal object StaticInitializersOptimization { expression.transformChildren(this, data) val callee = expression.actualCallee + /* + * There can be construction like `initInstance(constructorCall())` in IR + * Which can be transformed to `initInstance({ callClassStaticInits(); conctructorCall() })` + * which is not valid for code-gen, as it expects the intrinsic argument to be a constructor call. + * + * So we here fix it by postporcessing to `{ callClassStaticInitis(); initInstance(constructorCall()) }` + */ + if (tryGetIntrinsicType(expression) == IntrinsicType.INIT_INSTANCE) { + val constructorArg = expression.getValueArgument(1) + if (constructorArg is IrBlock) { + val realConstructorArg = constructorArg.statements.last() as IrConstructorCall + constructorArg.statements[constructorArg.statements.lastIndex] = expression.apply { + putValueArgument(1, realConstructorArg) + } + return constructorArg + } + } val body = callee.body ?: return expression val initializerCalls = (body as IrBlockBody).statements .take(2) // The very first statements by construction. diff --git a/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.kt b/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.kt index 941055690b7..0aecd9a04ea 100644 --- a/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.kt +++ b/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.kt @@ -18,14 +18,6 @@ fun getStackTrace() : List { open class Foo { open fun foo(): List { return emptyList() } - - companion object { - var trace: List = emptyList() - - init { - trace = getStackTrace() - } - } } private class Bar : Foo() { @@ -40,6 +32,16 @@ object Object { } } +class WithCompanion { + companion object { + var trace: List = emptyList() + + init { + trace = getStackTrace() + } + } +} + enum class E { A { init { diff --git a/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift b/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift index 25b20929c48..0d20b655a42 100644 --- a/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift +++ b/kotlin-native/backend.native/tests/framework/stacktraceBridges/stacktraceBridges.swift @@ -23,8 +23,8 @@ func testKotlin2Objc() throws { } func testCompanionObject() throws { - let trace = Foo.companion.trace - try assertTrue(trace[8].contains("objc2kotlin_kclass:Foo#companion")) + let trace = WithCompanion.companion.trace + try assertTrue(trace[8].contains("objc2kotlin_kclass:WithCompanion#companion")) } func testStandaloneObject() throws {