JVM IR: Remove varargs from CallableReferenceLowering

This commit is contained in:
Steven Schäfer
2019-07-31 16:32:35 +02:00
committed by max-kammerer
parent 99f1329c14
commit 4d8d65abec
2 changed files with 27 additions and 31 deletions
@@ -16,11 +16,12 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.irArray
import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
import org.jetbrains.kotlin.ir.builders.declarations.addFunction import org.jetbrains.kotlin.ir.builders.declarations.addFunction
@@ -30,7 +31,6 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
@@ -257,7 +257,7 @@ internal class CallableReferenceLowering(private val context: JvmBackendContext)
} }
} }
body = context.createIrBuilder(symbol).run { body = context.createJvmIrBuilder(symbol).run {
var unboundIndex = 0 var unboundIndex = 0
irExprBody(irCall(callee).apply { irExprBody(irCall(callee).apply {
for ((typeParameter, typeArgument) in typeArgumentsMap) { for ((typeParameter, typeArgument) in typeArgumentsMap) {
@@ -273,25 +273,26 @@ internal class CallableReferenceLowering(private val context: JvmBackendContext)
boundReceiver.second.type boundReceiver.second.type
) )
unboundIndex >= argumentTypes.size ->
// Unbound, but out of range - empty vararg or default value.
// TODO For suspend functions the last argument is continuation and it is implicit:
// irCall(getContinuationSymbol, listOf(ourSymbol.descriptor.returnType!!))
null
// If a vararg parameter corresponds to exactly one KFunction argument, which is an array, that array // If a vararg parameter corresponds to exactly one KFunction argument, which is an array, that array
// is forwarded as a spread. In all other cases, excess arguments are packed into a new array. // is forwarded as is. In all other cases, excess arguments are packed into a new array.
// //
// fun f(x: (Int, Array<String>) -> String) = x(0, arrayOf("OK", "FAIL")) // fun f(x: (Int, Array<String>) -> String) = x(0, arrayOf("OK", "FAIL"))
// fun g(x: (Int, String, String) -> String) = x(0, "OK", "FAIL") // fun g(x: (Int, String, String) -> String) = x(0, "OK", "FAIL")
// fun h(i: Int, vararg xs: String) = xs[i] // fun h(i: Int, vararg xs: String) = xs[i]
// f(::h) == g(::h) // f(::h) == g(::h)
// //
parameter.isVararg && (unboundIndex < argumentTypes.size - 1 || argumentTypes.last() != parameter.type) -> parameter.isVararg && unboundIndex < argumentTypes.size && parameter.type == valueParameters[unboundIndex].type ->
IrVarargImpl( irArray(parameter.type) { addSpread(irGet(valueParameters[unboundIndex++])) }
startOffset, endOffset, parameter.type, parameter.varargElementType!!, parameter.isVararg && (unboundIndex < argumentTypes.size || !parameter.hasDefaultValue()) ->
(unboundIndex until argumentTypes.size).map { irGet(valueParameters[unboundIndex++]) } irArray(parameter.type) {
) (unboundIndex until argumentTypes.size).forEach { +irGet(valueParameters[unboundIndex++]) }
}
unboundIndex >= argumentTypes.size ->
// Default value argument
// TODO For suspend functions the last argument is continuation and it is implicit:
// irCall(getContinuationSymbol, listOf(ourSymbol.descriptor.returnType!!))
null
else -> else ->
irGet(valueParameters[unboundIndex++]) irGet(valueParameters[unboundIndex++])
@@ -8,23 +8,23 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.irArray
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addFunction import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -52,19 +52,14 @@ private class FunctionNVarargBridgeLowering(val context: JvmBackendContext) :
expression.symbol.owner.name.asString() != "invoke") expression.symbol.owner.name.asString() != "invoke")
return super.visitFunctionAccess(expression) return super.visitFunctionAccess(expression)
return IrCallImpl( return context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol).run {
expression.startOffset, expression.endOffset, at(expression)
expression.type, functionNInvokeFun, functionNInvokeFun.descriptor, irCall(functionNInvokeFun).apply {
1, expression.origin dispatchReceiver = expression.dispatchReceiver
).apply { putValueArgument(0, irArray(backendContext.ir.symbols.array.typeWith(context.irBuiltIns.anyNType)) {
putTypeArgument(0, expression.type) (0 until expression.valueArgumentsCount).forEach { +expression.getValueArgument(it)!! }
dispatchReceiver = expression.dispatchReceiver })
putValueArgument(0, IrVarargImpl( }
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.ir.symbols.array.typeWith(context.irBuiltIns.anyNType),
context.irBuiltIns.anyNType,
(0 until expression.valueArgumentsCount).map { expression.getValueArgument(it)!! }
))
} }
} }