[FIR2IR] Introduce IrBlock for reordering arguments if needed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
acc5633811
commit
bae41ddf6d
+54
-5
@@ -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<FirValueParameter>, valueParameters: List<FirValueParameter>): 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()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
fun test(a: String, b: String): String {
|
||||
return a + b;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var invokeOrder = "";
|
||||
val expectedResult = "0_1_9"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var invokeOrder = "";
|
||||
val expectedResult = "1_0_1_9"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var invokeOrder = "";
|
||||
val expectedResult = "1_0_1_L"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
return Z().test()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KT-9277 Unexpected NullPointerException in an invocaton with named arguments
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -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"})
|
||||
|
||||
@@ -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"})
|
||||
|
||||
Vendored
-1
@@ -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
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
var res = ""
|
||||
|
||||
fun getM(): String {
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
FILE fqName:<root> 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 <root>'
|
||||
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 <root>'
|
||||
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 <root>'
|
||||
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 <root>'
|
||||
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 <root>' type=kotlin.Unit origin=null
|
||||
a: CALL 'public final fun noReorder1 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
b: CALL 'public final fun noReorder2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||
a: CALL 'public final fun reordered2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
b: CALL 'public final fun reordered1 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||
a: CALL 'public final fun reordered2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
b: CONST Int type=kotlin.Int value=1
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
fun foo(a: Int, b: Int) {}
|
||||
|
||||
fun noReorder1() = 1
|
||||
|
||||
Reference in New Issue
Block a user