diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt index 455663de5a4..d445332e8a5 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt @@ -8,6 +8,7 @@ import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunc import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering import org.jetbrains.kotlin.backend.common.lower.optimizations.FoldConstantLowering +import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.backend.konan.lower.* import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering @@ -106,6 +107,12 @@ internal val lateinitPhase = makeKonanModuleOpPhase( description = "Lateinit properties lowering" ) +internal val propertyAccessorInlinePhase = makeKonanModuleLoweringPhase( + ::PropertyAccessorInlineLowering, + name = "PropertyAccessorInline", + description = "Property accessor inline lowering" +) + internal val sharedVariablesPhase = makeKonanModuleLoweringPhase( ::SharedVariablesLowering, name = "SharedVariables", diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index 4c24ed52d02..66df2320878 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -391,6 +391,8 @@ internal val bitcodePhase = NamedCompilerPhase( ghaPhase then RTTIPhase then generateDebugInfoHeaderPhase then + propertyAccessorInlinePhase then // Have to run after link dependencies phase, because fields + // from dependencies can be changed during lowerings. escapeAnalysisPhase then localEscapeAnalysisPhase then codegenPhase then @@ -468,6 +470,9 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) { disableUnless(buildDFGPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) disableUnless(devirtualizationPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) disableUnless(escapeAnalysisPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) + // Inline accessors only in optimized builds due to separate compilation and possibility to get broken + // debug information. + disableUnless(propertyAccessorInlinePhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) disableUnless(dcePhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) disableUnless(ghaPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) disableUnless(verifyBitcodePhase, config.needCompilerVerification || getBoolean(KonanConfigKeys.VERIFY_BITCODE)) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt index 91e9913eb05..bb051fd43b6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt @@ -309,6 +309,30 @@ private class InlineClassTransformer(private val context: Context) : IrBuildingT return declaration } + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + // Make replacement only in optimized builds due to separate compilation and possibility to get broken + // debug information. + if (!context.shouldOptimize()) + return expression + + val property = expression.symbol.owner.correspondingPropertySymbol?.owner ?: return expression + + property.parent.let { + if (it is IrClass && it.isInline && property.backingField != null) { + expression.dispatchReceiver?.let { receiver -> + return builder.at(expression) + .irCall(symbols.reinterpret, expression.type, listOf(receiver.type, expression.type)) + .apply { + extensionReceiver = receiver + } + } + } + } + + return expression + } + private fun IrBuilderWithScope.irIsNull(expression: IrExpression): IrExpression { val binary = expression.type.computeBinaryType() return when (binary) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt index fbfd584ad21..e731dfe571e 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt @@ -82,9 +82,11 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo ) // We shall keep initializer for constants for compile-time instantiation. + // We suppose that if the property is const, then its initializer is IrConst. + // If this requirement isn't satisfied, then PropertyAccessorInlineLowering can fail. declaration.initializer = if (initExpression is IrConst<*> && - (initExpression.type.isPrimitiveType() || initExpression.type.isString())) { + declaration.correspondingPropertySymbol?.owner?.isConst == true) { IrExpressionBodyImpl(initExpression.copy()) } else { null