diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index ea8cbf4e959..d9501573132 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -305,31 +305,11 @@ internal class CallAndReferenceGenerator( val function = ((call.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir val valueParameters = function?.valueParameters + if (valueParameters != null) { - if (needArgumentReordering(argumentMapping.values, valueParameters)) { - return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply { - for ((argument, parameter) in argumentMapping) { - val parameterIndex = valueParameters.indexOf(parameter) - val irArgument = visitor.convertToIrExpression(argument) - if (irArgument.hasNoSideEffects()) { - putValueArgument(parameterIndex, irArgument) - } else { - val tempVar = declarationStorage.declareTemporaryVariable(irArgument, parameter.name.asString()).apply { - parent = conversionScope.parentFromStack() - } - this.statements.add(tempVar) - putValueArgument(parameterIndex, IrGetValueImpl(startOffset, endOffset, tempVar.symbol, null)) - } - } - this.statements.add(this@applyCallArguments) - } - } else { - for ((argument, parameter) in argumentMapping) { - val argumentExpression = visitor.convertToIrExpression(argument) - putValueArgument(valueParameters.indexOf(parameter), argumentExpression) - } - return this - } + return applyArgumentsWithReordering( + argumentMapping, valueParameters, visitor, conversionScope, declarationStorage + ) } } for ((index, argument) in call.arguments.withIndex()) { @@ -358,17 +338,6 @@ internal class CallAndReferenceGenerator( } } - private fun needArgumentReordering(parametersInActualOrder: Collection, valueParameters: List): Boolean { - var lastValueParameterIndex = -1 - for (parameter in parametersInActualOrder) { - val index = valueParameters.indexOf(parameter) - if (index < lastValueParameterIndex) { - return true - } - lastValueParameterIndex = index - } - return false - } private fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression { return when (this) { @@ -499,3 +468,51 @@ internal class CallAndReferenceGenerator( ) } } + +internal fun IrCallWithIndexedArgumentsBase.applyArgumentsWithReordering( + argumentMapping: Map, + valueParameters: List, + visitor: Fir2IrVisitor, + conversionScope: Fir2IrConversionScope, + declarationStorage: Fir2IrDeclarationStorage +): IrExpressionBase { + if (needArgumentReordering(argumentMapping.values, valueParameters)) { + return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply { + for ((argument, parameter) in argumentMapping) { + val parameterIndex = valueParameters.indexOf(parameter) + val irArgument = visitor.convertToIrExpression(argument) + if (irArgument.hasNoSideEffects()) { + putValueArgument(parameterIndex, irArgument) + } else { + val tempVar = declarationStorage.declareTemporaryVariable(irArgument, parameter.name.asString()).apply { + parent = conversionScope.parentFromStack() + } + this.statements.add(tempVar) + putValueArgument(parameterIndex, IrGetValueImpl(startOffset, endOffset, tempVar.symbol, null)) + } + } + this.statements.add(this@applyArgumentsWithReordering) + } + } else { + for ((argument, parameter) in argumentMapping) { + val argumentExpression = visitor.convertToIrExpression(argument) + putValueArgument(valueParameters.indexOf(parameter), argumentExpression) + } + return this + } +} + +private fun needArgumentReordering( + parametersInActualOrder: Collection, + valueParameters: List +): Boolean { + var lastValueParameterIndex = -1 + for (parameter in parametersInActualOrder) { + val index = valueParameters.indexOf(parameter) + if (index < lastValueParameterIndex) { + return true + } + lastValueParameterIndex = index + } + return false +} diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index 45b9c8a27a6..44d349116f5 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression import org.jetbrains.kotlin.fir.expressions.arguments import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol @@ -238,10 +239,22 @@ internal class ClassMemberGenerator( constructedIrType, irConstructorSymbol ) - }.apply { - for ((index, argument) in arguments.withIndex()) { - val argumentExpression = visitor.convertToIrExpression(argument) - putValueArgument(index, argumentExpression) + }.let { + val argumentMapping = mutableMapOf() + val valueParameters = constructorSymbol.fir.valueParameters + for (argument in arguments) { + if (argument is FirNamedArgumentExpression) { + valueParameters.firstOrNull { it.name == argument.name }?.let { argumentMapping[argument] = it } + } + } + if (argumentMapping.size == valueParameters.size) { + it.applyArgumentsWithReordering(argumentMapping, valueParameters, visitor, conversionScope, declarationStorage) + } else { + for ((index, argument) in arguments.withIndex()) { + val argumentExpression = visitor.convertToIrExpression(argument) + it.putValueArgument(index, argumentExpression) + } + it } } } diff --git a/compiler/testData/codegen/box/argumentOrder/argumentOrderInObjectSuperCall.kt b/compiler/testData/codegen/box/argumentOrder/argumentOrderInObjectSuperCall.kt index be802dc4abf..b194d4365b3 100644 --- a/compiler/testData/codegen/box/argumentOrder/argumentOrderInObjectSuperCall.kt +++ b/compiler/testData/codegen/box/argumentOrder/argumentOrderInObjectSuperCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR var result = "fail" open class Base(val o: String, val k: String) diff --git a/compiler/testData/codegen/box/argumentOrder/argumentOrderInSuperCall.kt b/compiler/testData/codegen/box/argumentOrder/argumentOrderInSuperCall.kt index 588a6784dff..2f865397b1c 100644 --- a/compiler/testData/codegen/box/argumentOrder/argumentOrderInSuperCall.kt +++ b/compiler/testData/codegen/box/argumentOrder/argumentOrderInSuperCall.kt @@ -1,4 +1,4 @@ -// IGNORE_BACKEND_FIR: JVM_IR + var result = "fail" open class Base(val o: String, val k: String) diff --git a/compiler/testData/codegen/box/enum/constructorWithReordering.kt b/compiler/testData/codegen/box/enum/constructorWithReordering.kt index f3e563f1c8f..0ff1d169734 100644 --- a/compiler/testData/codegen/box/enum/constructorWithReordering.kt +++ b/compiler/testData/codegen/box/enum/constructorWithReordering.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS fun f(): String = "O" fun g(): String = "K" diff --git a/compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsLocal_kt16858.kt b/compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsLocal_kt16858.kt index 2ca90a256ff..34cca882b86 100644 --- a/compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsLocal_kt16858.kt +++ b/compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsLocal_kt16858.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR open class A(val a: String, val b: Int) fun box(): String { diff --git a/compiler/testData/codegen/box/super/superConstructor/kt18356.kt b/compiler/testData/codegen/box/super/superConstructor/kt18356.kt index 79d75d4691c..150d2f5dd85 100644 --- a/compiler/testData/codegen/box/super/superConstructor/kt18356.kt +++ b/compiler/testData/codegen/box/super/superConstructor/kt18356.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR open class Base(val addr: Long, val name: String) fun box(): String { diff --git a/compiler/testData/codegen/box/super/superConstructor/kt18356_2.kt b/compiler/testData/codegen/box/super/superConstructor/kt18356_2.kt index 4c1662196db..9773342f5fa 100644 --- a/compiler/testData/codegen/box/super/superConstructor/kt18356_2.kt +++ b/compiler/testData/codegen/box/super/superConstructor/kt18356_2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR abstract class Base(val s: String, vararg ints: Int) fun foo(s: String, ints: IntArray) = object : Base(ints = *ints, s = s) {} diff --git a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt index 45883b8f26e..9a16af25784 100644 --- a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt +++ b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt @@ -48,9 +48,14 @@ FILE fqName: fileName:/argumentReorderingInDelegatingConstructorCall.kt VALUE_PARAMETER name:xx index:0 type:kotlin.Int VALUE_PARAMETER name:yy index:1 type:kotlin.Int BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'public constructor (x: kotlin.Int, y: kotlin.Int) [primary] declared in .Base' - x: GET_VAR 'yy: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null - y: GET_VAR 'xx: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null + BLOCK type=.Base origin=ARGUMENTS_REORDERING_FOR_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val] + GET_VAR 'yy: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val] + GET_VAR 'xx: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null + DELEGATING_CONSTRUCTOR_CALL 'public constructor (x: kotlin.Int, y: kotlin.Int) [primary] declared in .Base' + x: GET_VAR 'val tmp_1: kotlin.Int [val] declared in .Test1.' type=kotlin.Int origin=null + y: GET_VAR 'val tmp_0: kotlin.Int [val] declared in .Test1.' type=kotlin.Int origin=null INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test1 modality:FINAL visibility:public superTypes:[.Base]' PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.Base) returnType:kotlin.Int [fake_override] @@ -90,9 +95,14 @@ FILE fqName: fileName:/argumentReorderingInDelegatingConstructorCall.kt VALUE_PARAMETER name:yyy index:1 type:kotlin.Int VALUE_PARAMETER name:a index:2 type:kotlin.Any BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'public constructor (xx: kotlin.Int, yy: kotlin.Int) declared in .Test2' - xx: GET_VAR 'yyy: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null - yy: GET_VAR 'xxx: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null + BLOCK type=.Test2 origin=ARGUMENTS_REORDERING_FOR_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val] + GET_VAR 'yyy: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null + VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val] + GET_VAR 'xxx: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null + DELEGATING_CONSTRUCTOR_CALL 'public constructor (xx: kotlin.Int, yy: kotlin.Int) declared in .Test2' + xx: GET_VAR 'val tmp_3: kotlin.Int [val] declared in .Test2.' type=kotlin.Int origin=null + yy: GET_VAR 'val tmp_2: kotlin.Int [val] declared in .Test2.' type=kotlin.Int origin=null PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.Base) returnType:kotlin.Int [fake_override] correspondingProperty: PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] diff --git a/compiler/testData/ir/irText/classes/enum.fir.txt b/compiler/testData/ir/irText/classes/enum.fir.txt index 926a84af3ff..0aa02b48ac8 100644 --- a/compiler/testData/ir/irText/classes/enum.fir.txt +++ b/compiler/testData/ir/irText/classes/enum.fir.txt @@ -790,9 +790,14 @@ FILE fqName: fileName:/enum.kt $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.TestEnum6.TEST CONSTRUCTOR visibility:private <> () returnType:.TestEnum6.TEST [primary] BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int, y: kotlin.Int) [primary] declared in .TestEnum6' - x: CALL 'public final fun f (): kotlin.Int declared in ' type=kotlin.Int origin=null - y: CALL 'public final fun f (): kotlin.Int declared in ' type=kotlin.Int origin=null + BLOCK type=.TestEnum6 origin=ARGUMENTS_REORDERING_FOR_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val] + CALL 'public final fun f (): kotlin.Int declared in ' type=kotlin.Int origin=null + VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val] + CALL 'public final fun f (): kotlin.Int declared in ' type=kotlin.Int origin=null + ENUM_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int, y: kotlin.Int) [primary] declared in .TestEnum6' + x: GET_VAR 'val tmp_1: kotlin.Int [val] declared in .TestEnum6.TEST.' type=kotlin.Int origin=null + y: GET_VAR 'val tmp_0: kotlin.Int [val] declared in .TestEnum6.TEST.' type=kotlin.Int origin=null INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_ENTRY name:TEST modality:FINAL visibility:private superTypes:[.TestEnum6]' PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.TestEnum6) returnType:kotlin.Int [fake_override]