From bae41ddf6d6d75df1f83590c5cdcc0b37fe1f8dd Mon Sep 17 00:00:00 2001 From: Juan Chen Date: Thu, 9 Apr 2020 16:56:14 -0700 Subject: [PATCH] [FIR2IR] Introduce IrBlock for reordering arguments if needed --- .../generators/CallAndReferenceGenerator.kt | 59 +++++++++++++++++-- .../codegen/box/argumentOrder/arguments.kt | 1 - .../codegen/box/argumentOrder/captured.kt | 1 - .../box/argumentOrder/capturedInExtension.kt | 1 - .../codegen/box/argumentOrder/defaults.kt | 1 - .../codegen/box/argumentOrder/extension.kt | 1 - .../box/argumentOrder/extensionInClass.kt | 1 - .../codegen/box/argumentOrder/kt9277.kt | 1 - .../codegen/box/argumentOrder/simple.kt | 1 - .../box/argumentOrder/simpleInClass.kt | 1 - .../defaultArgsWithSideEffects2.kt | 1 - .../box/intrinsics/throwableParamOrder.kt | 1 - .../callWithReorderedArguments.fir.txt | 32 ---------- .../expressions/callWithReorderedArguments.kt | 1 + 14 files changed, 55 insertions(+), 48 deletions(-) delete mode 100644 compiler/testData/ir/irText/expressions/callWithReorderedArguments.fir.txt 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 015f9590708..ea8cbf4e959 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 @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.backend.generators import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.psi @@ -33,6 +34,7 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.makeNotNull import org.jetbrains.kotlin.psi.KtPropertyDelegate +import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects internal class CallAndReferenceGenerator( private val components: Fir2IrComponents, @@ -304,11 +306,30 @@ internal class CallAndReferenceGenerator( ((call.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir val valueParameters = function?.valueParameters if (valueParameters != null) { - for ((argument, parameter) in argumentMapping) { - val argumentExpression = visitor.convertToIrExpression(argument) - putValueArgument(valueParameters.indexOf(parameter), argumentExpression) + 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 this } } for ((index, argument) in call.arguments.withIndex()) { @@ -337,6 +358,18 @@ 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) { is IrMemberAccessExpressionBase -> { @@ -356,6 +389,14 @@ internal class CallAndReferenceGenerator( ) } } + is IrBlockImpl -> apply { + if (statements.isNotEmpty()) { + val lastStatement = statements.last() + if (lastStatement is IrExpression) { + statements[statements.size - 1] = lastStatement.applyTypeArguments(access) + } + } + } else -> this } } @@ -418,6 +459,14 @@ internal class CallAndReferenceGenerator( } this } + is IrBlockImpl -> apply { + if (statements.isNotEmpty()) { + val lastStatement = statements.last() + if (lastStatement is IrExpression) { + statements[statements.size - 1] = lastStatement.applyReceivers(qualifiedAccess, explicitReceiverExpression) + } + } + } else -> this } } @@ -449,4 +498,4 @@ internal class CallAndReferenceGenerator( "Unresolved reference: ${calleeReference.render()}" ) } -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/argumentOrder/arguments.kt b/compiler/testData/codegen/box/argumentOrder/arguments.kt index 61a77ba7666..f3d4d9b9b33 100644 --- a/compiler/testData/codegen/box/argumentOrder/arguments.kt +++ b/compiler/testData/codegen/box/argumentOrder/arguments.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun test(a: String, b: String): String { return a + b; diff --git a/compiler/testData/codegen/box/argumentOrder/captured.kt b/compiler/testData/codegen/box/argumentOrder/captured.kt index 5a999f11343..f4f35913a07 100644 --- a/compiler/testData/codegen/box/argumentOrder/captured.kt +++ b/compiler/testData/codegen/box/argumentOrder/captured.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { var invokeOrder = ""; val expectedResult = "0_1_9" diff --git a/compiler/testData/codegen/box/argumentOrder/capturedInExtension.kt b/compiler/testData/codegen/box/argumentOrder/capturedInExtension.kt index 0f6769e5d68..cfd5329d520 100644 --- a/compiler/testData/codegen/box/argumentOrder/capturedInExtension.kt +++ b/compiler/testData/codegen/box/argumentOrder/capturedInExtension.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { var invokeOrder = ""; val expectedResult = "1_0_1_9" diff --git a/compiler/testData/codegen/box/argumentOrder/defaults.kt b/compiler/testData/codegen/box/argumentOrder/defaults.kt index d2ee59498fb..ebf9b4d7d19 100644 --- a/compiler/testData/codegen/box/argumentOrder/defaults.kt +++ b/compiler/testData/codegen/box/argumentOrder/defaults.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR var invokeOrder: String = "" fun test(x: Double = { invokeOrder += "x"; 1.0 }(), a: String, y: Long = { invokeOrder += "y"; 1 }(), b: String): String { diff --git a/compiler/testData/codegen/box/argumentOrder/extension.kt b/compiler/testData/codegen/box/argumentOrder/extension.kt index b73b305f4ba..86fff0d8e1f 100644 --- a/compiler/testData/codegen/box/argumentOrder/extension.kt +++ b/compiler/testData/codegen/box/argumentOrder/extension.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { var invokeOrder = ""; val expectedResult = "1_0_1_L" diff --git a/compiler/testData/codegen/box/argumentOrder/extensionInClass.kt b/compiler/testData/codegen/box/argumentOrder/extensionInClass.kt index df66cd14127..ed025997c74 100644 --- a/compiler/testData/codegen/box/argumentOrder/extensionInClass.kt +++ b/compiler/testData/codegen/box/argumentOrder/extensionInClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { return Z().test() } diff --git a/compiler/testData/codegen/box/argumentOrder/kt9277.kt b/compiler/testData/codegen/box/argumentOrder/kt9277.kt index a0135659baa..eb08fb7b719 100644 --- a/compiler/testData/codegen/box/argumentOrder/kt9277.kt +++ b/compiler/testData/codegen/box/argumentOrder/kt9277.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // KT-9277 Unexpected NullPointerException in an invocaton with named arguments fun box(): String { diff --git a/compiler/testData/codegen/box/argumentOrder/simple.kt b/compiler/testData/codegen/box/argumentOrder/simple.kt index 65277482515..112891c4d9a 100644 --- a/compiler/testData/codegen/box/argumentOrder/simple.kt +++ b/compiler/testData/codegen/box/argumentOrder/simple.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { var res = ""; var call = test(b = {res += "K"; "K"}(), a = {res+="O"; "O"}(), c = {res += "L"; "L"}) diff --git a/compiler/testData/codegen/box/argumentOrder/simpleInClass.kt b/compiler/testData/codegen/box/argumentOrder/simpleInClass.kt index 84cc2355aed..71bc1f7452c 100644 --- a/compiler/testData/codegen/box/argumentOrder/simpleInClass.kt +++ b/compiler/testData/codegen/box/argumentOrder/simpleInClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR fun box(): String { var res = ""; var call = Z("Z").test(b = {res += "K"; "K"}(), a = {res+="O"; "O"}(), c = {res += "L"; "L"}) diff --git a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt index 7d0b8554399..6d5f4315c10 100644 --- a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt +++ b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperComputationOrderOfTailrecDefaultParameters -// IGNORE_BACKEND_FIR: JVM_IR // Flag above doesn't matter cause 1 default value is passed explicitly in tail recursion call // DONT_RUN_GENERATED_CODE: JS diff --git a/compiler/testData/codegen/box/intrinsics/throwableParamOrder.kt b/compiler/testData/codegen/box/intrinsics/throwableParamOrder.kt index 68d6647fab4..7708a6de220 100644 --- a/compiler/testData/codegen/box/intrinsics/throwableParamOrder.kt +++ b/compiler/testData/codegen/box/intrinsics/throwableParamOrder.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR var res = "" fun getM(): String { diff --git a/compiler/testData/ir/irText/expressions/callWithReorderedArguments.fir.txt b/compiler/testData/ir/irText/expressions/callWithReorderedArguments.fir.txt deleted file mode 100644 index fcc441cf975..00000000000 --- a/compiler/testData/ir/irText/expressions/callWithReorderedArguments.fir.txt +++ /dev/null @@ -1,32 +0,0 @@ -FILE fqName: fileName:/callWithReorderedArguments.kt - FUN name:foo visibility:public modality:FINAL <> (a:kotlin.Int, b:kotlin.Int) returnType:kotlin.Unit - VALUE_PARAMETER name:a index:0 type:kotlin.Int - VALUE_PARAMETER name:b index:1 type:kotlin.Int - BLOCK_BODY - FUN name:noReorder1 visibility:public modality:FINAL <> () returnType:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun noReorder1 (): kotlin.Int declared in ' - CONST Int type=kotlin.Int value=1 - FUN name:noReorder2 visibility:public modality:FINAL <> () returnType:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun noReorder2 (): kotlin.Int declared in ' - CONST Int type=kotlin.Int value=2 - FUN name:reordered1 visibility:public modality:FINAL <> () returnType:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun reordered1 (): kotlin.Int declared in ' - CONST Int type=kotlin.Int value=1 - FUN name:reordered2 visibility:public modality:FINAL <> () returnType:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun reordered2 (): kotlin.Int declared in ' - CONST Int type=kotlin.Int value=2 - FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit - BLOCK_BODY - CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=null - a: CALL 'public final fun noReorder1 (): kotlin.Int declared in ' type=kotlin.Int origin=null - b: CALL 'public final fun noReorder2 (): kotlin.Int declared in ' type=kotlin.Int origin=null - CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=null - a: CALL 'public final fun reordered2 (): kotlin.Int declared in ' type=kotlin.Int origin=null - b: CALL 'public final fun reordered1 (): kotlin.Int declared in ' type=kotlin.Int origin=null - CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in ' type=kotlin.Unit origin=null - a: CALL 'public final fun reordered2 (): kotlin.Int declared in ' type=kotlin.Int origin=null - b: CONST Int type=kotlin.Int value=1 diff --git a/compiler/testData/ir/irText/expressions/callWithReorderedArguments.kt b/compiler/testData/ir/irText/expressions/callWithReorderedArguments.kt index 6ffebfe3a5b..845cca9f3fb 100644 --- a/compiler/testData/ir/irText/expressions/callWithReorderedArguments.kt +++ b/compiler/testData/ir/irText/expressions/callWithReorderedArguments.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun foo(a: Int, b: Int) {} fun noReorder1() = 1