From f55fd481e989ca185b72c7052a86b27f22b054f0 Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Mon, 24 Apr 2023 12:52:17 +0200 Subject: [PATCH] [K/N] Refactor default argument lowering to avoid boxing Current inline classes API is not compatible between different backends. So implementing common function required for this optimization was not possible in Native backend. So, common default arguments lowering was refactored to make bigger piece of code replaceable in backends. ^KT-57860 --- .../jetbrains/kotlin/backend/common/ir/Ir.kt | 6 ---- .../lower/DefaultArgumentFunctionFactory.kt | 18 +++++++--- .../lower/DefaultArgumentStubGenerator.kt | 18 +++++----- .../ir/backend/js/JsIrBackendContext.kt | 4 --- .../lower/JsDefaultArgumentFunctionFactory.kt | 9 +++-- .../lower/JsDefaultArgumentStubGenerator.kt | 10 +++--- .../js/lower/JsDefaultParameterInjector.kt | 9 +++-- .../JvmDefaultArgumentFunctionFactory.kt | 16 +++++++++ .../lower/JvmDefaultArgumentStubGenerator.kt | 7 +++- .../jvm/lower/JvmDefaultParameterInjector.kt | 10 +++--- .../kotlin/backend/jvm/JvmBackendContext.kt | 4 --- .../kotlin/backend/wasm/WasmLoweringPhases.kt | 4 +-- .../backend/konan/driver/phases/Lowerings.kt | 4 +-- .../NativeDefaultArgumentFunctionFactory.kt | 19 ++++++++++ ... => NativeDefaultArgumentStubGenerator.kt} | 8 +++-- ...r.kt => NativeDefaultParameterInjector.kt} | 9 +++-- .../backend.native/tests/build.gradle | 4 +++ .../filecheck/default_parameters_dont_box.kt | 36 +++++++++++++++++++ 18 files changed, 141 insertions(+), 54 deletions(-) create mode 100644 compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentFunctionFactory.kt create mode 100644 kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultArgumentFunctionFactory.kt rename kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/{KonanDefaultArgumentStubGenerator.kt => NativeDefaultArgumentStubGenerator.kt} (79%) rename kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/{KonanDefaultParameterInjector.kt => NativeDefaultParameterInjector.kt} (88%) create mode 100644 kotlin-native/backend.native/tests/filecheck/default_parameters_dont_box.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index fcff6f2f54d..313d178cd8a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -26,14 +26,8 @@ abstract class Ir(val context: T) { abstract val symbols: Symbols - val defaultParameterDeclarationsCache = mutableMapOf() - internal val localScopeWithCounterMap = LocalDeclarationsLowering.LocalScopeWithCounterMap() - // If irType is an inline class type, return the underlying type according to the - // unfolding rules of the current backend. Otherwise, returns null. - open fun unfoldInlineClassType(irType: IrType): IrType? = null - open fun shouldGenerateHandlerParameterForDefaultBodyFun() = false } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentFunctionFactory.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentFunctionFactory.kt index 534c44258e9..9a906f8a99d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentFunctionFactory.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentFunctionFactory.kt @@ -15,12 +15,14 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.utils.* import org.jetbrains.kotlin.name.Name -abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendContext) { +abstract class DefaultArgumentFunctionFactory(val context: CommonBackendContext) { + protected fun IrFunction.generateDefaultArgumentsFunctionName() = Name.identifier("${name}\$default") @@ -40,11 +42,19 @@ abstract class DefaultArgumentFunctionFactory(open val context: CommonBackendCon contextReceiverParametersCount = original.contextReceiverParametersCount } - protected fun IrFunction.copyValueParametersFrom(original: IrFunction, wrapWithNullable: Boolean = true) { + /** + * Whether `null` will be used for this type if no argument is passed. + * In that case, the type of the default dispatch function will be made nullable. + * + * By default, always returns `true` – this is valid, but suboptimal. + * Better performance can be achieved in a backend-specific way. + */ + protected open fun IrType.hasNullAsUndefinedValue(): Boolean = true + + protected fun IrFunction.copyValueParametersFrom(original: IrFunction) { valueParameters = original.valueParameters.memoryOptimizedMap { val newType = it.type.remapTypeParameters(original.classIfConstructor, classIfConstructor) - val makeNullable = wrapWithNullable && it.defaultValue != null && - (context.ir.unfoldInlineClassType(it.type) ?: it.type) !in context.irBuiltIns.primitiveIrTypes + val makeNullable = it.defaultValue != null && it.type.hasNullAsUndefinedValue() it.copyTo( this, type = if (makeNullable) newType.makeNullable() else newType, diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index 210f2f63ba3..85109f6a2cc 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -33,12 +33,12 @@ import org.jetbrains.kotlin.utils.memoryOptimizedPlus // TODO: fix expect/actual default parameters -open class DefaultArgumentStubGenerator( - open val context: CommonBackendContext, +open class DefaultArgumentStubGenerator( + val context: TContext, + private val factory: DefaultArgumentFunctionFactory, private val skipInlineMethods: Boolean = true, private val skipExternalMethods: Boolean = false, - private val forceSetOverrideSymbols: Boolean = true, - private val factory: DefaultArgumentFunctionFactory = MaskedDefaultArgumentFunctionFactory(context) + private val forceSetOverrideSymbols: Boolean = true ) : DeclarationTransformer { override val withLocalDeclarations: Boolean get() = true @@ -255,12 +255,12 @@ open class DefaultArgumentStubGenerator( private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" } } -open class DefaultParameterInjector( - open val context: CommonBackendContext, +open class DefaultParameterInjector( + protected val context: TContext, + protected val factory: DefaultArgumentFunctionFactory, protected val skipInline: Boolean = true, protected val skipExternalMethods: Boolean = false, protected val forceSetOverrideSymbols: Boolean = true, - protected val factory: DefaultArgumentFunctionFactory = MaskedDefaultArgumentFunctionFactory(context), ) : IrElementTransformerVoid(), BodyLoweringPass { override fun lower(irBody: IrBody, container: IrDeclaration) { @@ -499,8 +499,8 @@ class DefaultParameterPatchOverridenSymbolsLowering( } } -private class MaskedDefaultArgumentFunctionFactory(context: CommonBackendContext) : DefaultArgumentFunctionFactory(context) { - override fun IrFunction.generateDefaultArgumentStubFrom(original: IrFunction, useConstructorMarker: Boolean) { +open class MaskedDefaultArgumentFunctionFactory(context: CommonBackendContext) : DefaultArgumentFunctionFactory(context) { + final override fun IrFunction.generateDefaultArgumentStubFrom(original: IrFunction, useConstructorMarker: Boolean) { copyAttributesFrom(original) copyTypeParametersFrom(original) copyReturnTypeFrom(original) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 2cae70a3817..35d8e2d3311 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -288,10 +288,6 @@ class JsIrBackendContext( } } - override fun unfoldInlineClassType(irType: IrType): IrType? { - return inlineClassesUtils.getInlinedClass(irType)?.typeWith() - } - override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentFunctionFactory.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentFunctionFactory.kt index e4d35c2fd4f..ae7082b1cfa 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentFunctionFactory.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentFunctionFactory.kt @@ -5,11 +5,13 @@ package org.jetbrains.kotlin.ir.backend.js.lower +import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.lower.DefaultArgumentFunctionFactory import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.copyTypeParametersFrom import org.jetbrains.kotlin.ir.util.defaultType @@ -17,13 +19,16 @@ import org.jetbrains.kotlin.ir.util.isTopLevel import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.name.Name -class JsDefaultArgumentFunctionFactory(override val context: JsIrBackendContext) : DefaultArgumentFunctionFactory(context) { +class JsDefaultArgumentFunctionFactory(context: CommonBackendContext) : DefaultArgumentFunctionFactory(context) { + + override fun IrType.hasNullAsUndefinedValue() = false + override fun IrFunction.generateDefaultArgumentStubFrom(original: IrFunction, useConstructorMarker: Boolean) { copyAttributesFrom(original) copyTypeParametersFrom(original) copyReturnTypeFrom(original) copyReceiversFrom(original) - copyValueParametersFrom(original, wrapWithNullable = false) + copyValueParametersFrom(original) if (!original.isTopLevel) { introduceContextParam() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt index c93279cc06f..e020dc36770 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultArgumentStubGenerator.kt @@ -29,12 +29,12 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.memoryOptimizedMap import org.jetbrains.kotlin.utils.memoryOptimizedPlus -class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) : - DefaultArgumentStubGenerator( - context, +class JsDefaultArgumentStubGenerator(context: JsIrBackendContext) : + DefaultArgumentStubGenerator( + context = context, + factory = JsDefaultArgumentFunctionFactory(context), skipExternalMethods = true, - forceSetOverrideSymbols = false, - factory = JsDefaultArgumentFunctionFactory(context) + forceSetOverrideSymbols = false ) { private fun IrBuilderWithScope.createDefaultResolutionExpression( diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultParameterInjector.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultParameterInjector.kt index d06a9c77689..0d644075bf3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultParameterInjector.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsDefaultParameterInjector.kt @@ -22,16 +22,15 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.copyAnnotations -import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.isTopLevel import org.jetbrains.kotlin.ir.util.isVararg -class JsDefaultParameterInjector(override val context: JsIrBackendContext) : - DefaultParameterInjector( +class JsDefaultParameterInjector(context: JsIrBackendContext) : + DefaultParameterInjector( context, + factory = JsDefaultArgumentFunctionFactory(context), skipExternalMethods = true, - forceSetOverrideSymbols = false, - factory = JsDefaultArgumentFunctionFactory(context) + forceSetOverrideSymbols = false ) { override fun nullConst(startOffset: Int, endOffset: Int, irParameter: IrValueParameter): IrExpression? = if (irParameter.isVararg && !irParameter.hasDefaultValue()) { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentFunctionFactory.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentFunctionFactory.kt new file mode 100644 index 00000000000..505e5fb8c28 --- /dev/null +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentFunctionFactory.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2023 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 org.jetbrains.kotlin.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.jvm.InlineClassAbi +import org.jetbrains.kotlin.ir.types.IrType + +internal class JvmDefaultArgumentFunctionFactory(context: CommonBackendContext) : MaskedDefaultArgumentFunctionFactory(context) { + override fun IrType.hasNullAsUndefinedValue() = + (InlineClassAbi.unboxType(this) ?: this) !in context.irBuiltIns.primitiveIrTypes +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt index 23d0f15674f..e155fe4b1d8 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultArgumentStubGenerator.kt @@ -19,7 +19,12 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.util.isFinalClass import org.jetbrains.kotlin.ir.util.isTopLevelDeclaration -class JvmDefaultArgumentStubGenerator(override val context: JvmBackendContext) : DefaultArgumentStubGenerator(context, false, false) { +class JvmDefaultArgumentStubGenerator(context: JvmBackendContext) : DefaultArgumentStubGenerator( + context = context, + factory = JvmDefaultArgumentFunctionFactory(context), + skipInlineMethods = false, + skipExternalMethods = false +) { override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub() override fun useConstructorMarker(function: IrFunction): Boolean = diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt index 948d2916251..f8c2bde37f4 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmDefaultParameterInjector.kt @@ -16,10 +16,12 @@ import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.types.IrType -class JvmDefaultParameterInjector(context: JvmBackendContext) : - DefaultParameterInjector(context, skipInline = false, skipExternalMethods = false) { - - override val context: JvmBackendContext get() = super.context as JvmBackendContext +class JvmDefaultParameterInjector(context: JvmBackendContext) : DefaultParameterInjector( + context = context, + factory = JvmDefaultArgumentFunctionFactory(context), + skipInline = false, + skipExternalMethods = false +) { override fun nullConst(startOffset: Int, endOffset: Int, irParameter: IrValueParameter): IrExpression? = nullConst(startOffset, endOffset, irParameter.type) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index bd687cc7a6d..179e2f9aabf 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -293,10 +293,6 @@ class JvmBackendContext( ) : Ir(this) { override val symbols = JvmSymbols(this@JvmBackendContext, symbolTable) - override fun unfoldInlineClassType(irType: IrType): IrType? { - return InlineClassAbi.unboxType(irType) - } - override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt index 8fb9e2d0679..c470ec74c16 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt @@ -369,7 +369,7 @@ private val addMainFunctionCallsLowering = makeCustomWasmModulePhase( ) private val defaultArgumentStubGeneratorPhase = makeWasmModulePhase( - { context -> DefaultArgumentStubGenerator(context, skipExternalMethods = true) }, + { context -> DefaultArgumentStubGenerator(context, MaskedDefaultArgumentFunctionFactory(context), skipExternalMethods = true) }, name = "DefaultArgumentStubGenerator", description = "Generate synthetic stubs for functions with default parameter values" ) @@ -382,7 +382,7 @@ private val defaultArgumentPatchOverridesPhase = makeWasmModulePhase( ) private val defaultParameterInjectorPhase = makeWasmModulePhase( - { context -> DefaultParameterInjector(context, skipExternalMethods = true) }, + { context -> DefaultParameterInjector(context, MaskedDefaultArgumentFunctionFactory(context), skipExternalMethods = true) }, name = "DefaultParameterInjector", description = "Replace call site with default parameters with corresponding stub function", prerequisite = setOf(innerClassesLoweringPhase) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt index 96fe7f2f89a..c5be1ace832 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/Lowerings.kt @@ -226,9 +226,9 @@ private val volatilePhase = createFileLoweringPhase( private val defaultParameterExtentPhase = createFileLoweringPhase( { context, irFile -> - KonanDefaultArgumentStubGenerator(context).lower(irFile) + NativeDefaultArgumentStubGenerator(context).lower(irFile) DefaultParameterCleaner(context, replaceDefaultValuesWithStubs = true).lower(irFile) - KonanDefaultParameterInjector(context).lower(irFile) + NativeDefaultParameterInjector(context).lower(irFile) }, name = "DefaultParameterExtent", description = "Default parameter extent lowering", diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultArgumentFunctionFactory.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultArgumentFunctionFactory.kt new file mode 100644 index 00000000000..b2e8808cae7 --- /dev/null +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultArgumentFunctionFactory.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2023 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 org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.lower.* +import org.jetbrains.kotlin.backend.konan.PrimitiveBinaryType +import org.jetbrains.kotlin.backend.konan.computePrimitiveBinaryTypeOrNull +import org.jetbrains.kotlin.ir.types.IrType + +internal class NativeDefaultArgumentFunctionFactory(context: CommonBackendContext) : MaskedDefaultArgumentFunctionFactory(context) { + override fun IrType.hasNullAsUndefinedValue(): Boolean { + val binaryType = computePrimitiveBinaryTypeOrNull() ?: return true + return binaryType == PrimitiveBinaryType.POINTER || binaryType == PrimitiveBinaryType.VECTOR128 + } +} \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultArgumentStubGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultArgumentStubGenerator.kt similarity index 79% rename from kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultArgumentStubGenerator.kt rename to kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultArgumentStubGenerator.kt index de2b529727e..aba0826566f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultArgumentStubGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultArgumentStubGenerator.kt @@ -12,9 +12,11 @@ import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.IrExpression -internal class KonanDefaultArgumentStubGenerator(override val context: Context) - : DefaultArgumentStubGenerator(context, skipInlineMethods = false) -{ +internal class NativeDefaultArgumentStubGenerator(context: Context) : DefaultArgumentStubGenerator( + context = context, + factory = NativeDefaultArgumentFunctionFactory(context), + skipInlineMethods = false +) { override fun IrBlockBodyBuilder.selectArgumentOrDefault( defaultFlag: IrExpression, parameter: IrValueParameter, diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultParameterInjector.kt similarity index 88% rename from kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt rename to kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultParameterInjector.kt index ca279a73e41..2399a0466eb 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/KonanDefaultParameterInjector.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/NativeDefaultParameterInjector.kt @@ -15,11 +15,14 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.irCall -internal class KonanDefaultParameterInjector(private val konanContext: KonanBackendContext) - : DefaultParameterInjector(konanContext, skipInline = false) { +internal class NativeDefaultParameterInjector(context: KonanBackendContext) : DefaultParameterInjector( + context = context, + factory = NativeDefaultArgumentFunctionFactory(context), + skipInline = false +) { override fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression { - val symbols = konanContext.ir.symbols + val symbols = context.ir.symbols val nullConstOfEquivalentType = when (type.computePrimitiveBinaryTypeOrNull()) { null -> IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType) diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index b6905b50bf5..2487b6b9511 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -6487,6 +6487,10 @@ fileCheckTest("filecheck_intrinsics") { annotatedSource = project.file('filecheck/intrinsics.kt') } +fileCheckTest("filecheck_default_parameters_dont_box") { + annotatedSource = project.file('filecheck/default_parameters_dont_box.kt') +} + task kt53119_side_effect(type: KonanLocalTest) { useGoldenData = true source = "codegen/stringConcatenationTypeNarrowing/kt53119_side_effect.kt" diff --git a/kotlin-native/backend.native/tests/filecheck/default_parameters_dont_box.kt b/kotlin-native/backend.native/tests/filecheck/default_parameters_dont_box.kt new file mode 100644 index 00000000000..89cedb8dcdc --- /dev/null +++ b/kotlin-native/backend.native/tests/filecheck/default_parameters_dont_box.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2023 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. + */ + +value class A(val i: Int) +value class B(val a: A) +value class C(val s: String) + +fun defaultInt(a: Int = 1, aa: Int = 1) = a +fun defaultA(a: A = A(1), aa: A = A(1)) = a.i +fun defaultB(b: B = B(A(1)), bb: B = B(A(1))) = b.a.i +fun defaultC(c: C = C("1"), cc: C = C("1")) = c.s + +// CHECK-LABEL: "kfun:#main(){}" +fun main(){ + // CHECK-LABEL: entry + // CHECK-NOT: + // CHECK-NOT: + // CHECK-NOT: + // CHECK-NOT: + + defaultInt() + defaultA() + defaultB() + defaultC() + defaultInt(1) + defaultA(A(1)) + defaultB(B(A(1))) + defaultC(C("1")) + defaultInt(1, 1) + defaultA(A(1), A(1)) + defaultB(B(A(1)), B(A(1))) + defaultC(C("1"), C("1")) + // CHECK-LABEL: epilogue +} \ No newline at end of file