Move extension receiver to value parameters for static functions created

during InlineClassLowering phase.

This was the only place where both dispatch and extension receivers were
NOT moved to value parameters, which meant that the receivers were not
following the conventional ordering.

Merged createStaticBodilessMethod with createStaticFunctionWithReceivers
and the latter was moved to backend/common/ir/IrUtils.kt.
This commit is contained in:
Mark Punzalan
2019-06-27 21:42:44 -07:00
committed by max-kammerer
parent 1abdf0561a
commit 969478481e
13 changed files with 129 additions and 197 deletions
@@ -20,9 +20,11 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.Scope
@@ -499,3 +501,58 @@ fun IrClass.addFakeOverrides() {
declarations += fakeOverriddenFunctions.values
}
fun createStaticFunctionWithReceivers(
irParent: IrDeclarationParent,
name: Name,
oldFunction: IrFunction,
dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type,
origin: IrDeclarationOrigin = oldFunction.origin,
copyBody: Boolean = true
): IrSimpleFunction {
val descriptor = WrappedSimpleFunctionDescriptor(Annotations.EMPTY, oldFunction.descriptor.source)
return IrFunctionImpl(
oldFunction.startOffset, oldFunction.endOffset,
origin,
IrSimpleFunctionSymbolImpl(descriptor),
name,
oldFunction.visibility,
Modality.FINAL,
oldFunction.returnType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false
).apply {
descriptor.bind(this)
parent = irParent
copyTypeParametersFrom(oldFunction)
annotations.addAll(oldFunction.annotations)
var offset = 0
val dispatchReceiver = oldFunction.dispatchReceiverParameter?.copyTo(
this,
name = Name.identifier("this"),
index = offset++,
type = dispatchReceiverType!!
)
val extensionReceiver = oldFunction.extensionReceiverParameter?.copyTo(
this,
name = Name.identifier("receiver"),
index = offset++
)
valueParameters.addAll(listOfNotNull(dispatchReceiver, extensionReceiver) +
oldFunction.valueParameters.map { it.copyTo(this, index = it.index + offset) }
)
val mapping: Map<IrValueParameter, IrValueParameter> =
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
.zip(valueParameters).toMap()
if (copyBody) {
body = oldFunction.body
?.transform(VariableRemapper(mapping), null)
?.patchDeclarationParents(this)
}
metadata = oldFunction.metadata
}
}
@@ -8,18 +8,13 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -142,10 +137,12 @@ class InlineClassLowering(val context: BackendContext) {
staticMethod.valueParameters[0]
function.extensionReceiverParameter ->
staticMethod.extensionReceiverParameter!!
staticMethod.valueParameters[1]
in function.valueParameters ->
staticMethod.valueParameters[valueDeclaration.index + 1]
in function.valueParameters -> {
val offset = if (function.extensionReceiverParameter != null) 2 else 1
staticMethod.valueParameters[valueDeclaration.index + offset]
}
else -> return expression
}
@@ -163,13 +160,14 @@ class InlineClassLowering(val context: BackendContext) {
+irReturn(
irCall(staticMethod).apply {
val parameters =
listOf(function.dispatchReceiverParameter!!) + function.valueParameters
listOfNotNull(
function.dispatchReceiverParameter!!,
function.extensionReceiverParameter
) + function.valueParameters
for ((index, valueParameter) in parameters.withIndex()) {
putValueArgument(index, irGet(valueParameter))
}
extensionReceiver = function.extensionReceiverParameter?.let { irGet(it) }
}
)
}
@@ -190,7 +188,7 @@ class InlineClassLowering(val context: BackendContext) {
return expression
}
return irCall(expression, getOrCreateStaticMethod(function), dispatchReceiverAsArgument = false)
return irCall(expression, getOrCreateStaticMethod(function))
}
override fun visitCall(expression: IrCall): IrExpression {
@@ -208,7 +206,7 @@ class InlineClassLowering(val context: BackendContext) {
return irCall(
expression,
getOrCreateStaticMethod(function),
dispatchReceiverAsArgument = (function is IrSimpleFunction)
receiversAsArguments = (function is IrSimpleFunction)
)
}
@@ -219,11 +217,7 @@ class InlineClassLowering(val context: BackendContext) {
return when {
!klass.isInline -> expression
function.isPrimary -> irConstructorCall(expression, function)
else -> irCall(expression, getOrCreateStaticMethod(function)).apply {
(0 until expression.valueArgumentsCount).forEach {
putValueArgument(it, expression.getValueArgument(it)!!)
}
}
else -> irCall(expression, getOrCreateStaticMethod(function))
}
}
@@ -242,36 +236,6 @@ class InlineClassLowering(val context: BackendContext) {
else -> Name.identifier(asString() + INLINE_CLASS_IMPL_SUFFIX)
}
private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction {
val descriptor = WrappedSimpleFunctionDescriptor()
return IrFunctionImpl(
function.startOffset,
function.endOffset,
function.origin,
IrSimpleFunctionSymbolImpl(descriptor),
function.name.toInlineClassImplementationName(),
function.visibility,
Modality.FINAL,
function.returnType,
function.isInline,
function.isExternal,
(function is IrSimpleFunction && function.isTailrec),
(function is IrSimpleFunction && function.isSuspend)
).apply {
descriptor.bind(this)
copyTypeParametersFrom(function)
annotations += function.annotations
dispatchReceiverParameter = null
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this)
if (function is IrSimpleFunction) {
valueParameters.add(function.dispatchReceiverParameter!!.let { p -> p.copyTo(this, index = p.index + 1) })
valueParameters += function.valueParameters.map { p -> p.copyTo(this, index = p.index + 1) }
} else {
valueParameters += function.valueParameters.map { p -> p.copyTo(this) }
}
parent = function.parent
assert(isStaticMethodOfClass)
}
}
private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction =
createStaticFunctionWithReceivers(function.parent, function.name.toInlineClassImplementationName(), function, copyBody = false)
}
@@ -47,7 +47,7 @@ internal fun <K> MutableMap<K, (IrFunctionAccessExpression) -> IrExpression>.add
internal typealias MemberToTransformer = HashMap<SimpleMemberKey, (IrFunctionAccessExpression) -> IrExpression>
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunctionSymbol) {
add(type, name) { irCall(it, v, dispatchReceiverAsArgument = true) }
add(type, name) { irCall(it, v, receiversAsArguments = true) }
}
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunction) {
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.isStaticMethodOfClass
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.types.getClass
@@ -53,7 +53,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
comparator.owner.returnType,
comparator
).apply {
putValueArgument(0, irCall(call, intrinsics.longCompareToLong, argumentAsDispatchReceiver = true))
putValueArgument(0, irCall(call, intrinsics.longCompareToLong, argumentsAsReceivers = true))
putValueArgument(1, JsIrBuilder.buildInt(irBuiltIns.intType, 0))
}
}
@@ -95,7 +95,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
chooseEqualityOperatorForPrimitiveTypes(call)
!isLhsPrimitive && !lhs.type.isNullable() && equalsMethod != null ->
irCall(call, equalsMethod.symbol, argumentAsDispatchReceiver = true)
irCall(call, equalsMethod.symbol, argumentsAsReceivers = true)
else ->
irCall(call, intrinsics.jsEquals)
@@ -127,7 +127,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
// Use runtime function call in case when receiverType is a primitive JS type that doesn't have `compareTo` method,
// or has a potential to be primitive type (being fake overridden from `Comparable`)
function.isMethodOfPrimitiveJSType() || function.isFakeOverriddenFromComparable() ->
irCall(call, intrinsics.jsCompareTo, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsCompareTo, receiversAsArguments = true)
// Valid `compareTo` method must be present at this point
else ->
@@ -144,12 +144,12 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
// `Any.equals` works as identity operator
call.isSuperToAny() ->
irCall(call, intrinsics.jsEqeqeq, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsEqeqeq, receiversAsArguments = true)
// Use runtime function call in case when receiverType is a primitive JS type that doesn't have `equals` method,
// or has a potential to be primitive type (being fake overridden from `Any`)
function.isMethodOfPotentiallyPrimitiveJSType() ->
irCall(call, intrinsics.jsEquals, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsEquals, receiversAsArguments = true)
// Valid `equals` method must be present at this point
else -> call
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
import org.jetbrains.kotlin.name.FqName
@@ -29,9 +29,9 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
put(Name.identifier("toString")) { call ->
if (shouldReplaceToStringWithRuntimeCall(call)) {
if ((call as IrCall).isSuperToAny()) {
irCall(call, intrinsics.jsAnyToString, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsAnyToString, receiversAsArguments = true)
} else {
irCall(call, intrinsics.jsToString, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsToString, receiversAsArguments = true)
}
} else {
call
@@ -41,9 +41,9 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
put(Name.identifier("hashCode")) { call ->
if (call.symbol.owner.isFakeOverriddenFromAny()) {
if ((call as IrCall).isSuperToAny()) {
irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsGetObjectHashCode, receiversAsArguments = true)
} else {
irCall(call, intrinsics.jsHashCode, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsHashCode, receiversAsArguments = true)
}
} else {
call
@@ -46,9 +46,9 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
irBuiltIns.booleanType.let {
// These operators are not short-circuit -- using bitwise operators '&', '|', '^' followed by coercion to boolean
add(it, OperatorNames.AND) { call -> toBoolean(irCall(call, intrinsics.jsBitAnd, dispatchReceiverAsArgument = true)) }
add(it, OperatorNames.OR) { call -> toBoolean(irCall(call, intrinsics.jsBitOr, dispatchReceiverAsArgument = true)) }
add(it, OperatorNames.XOR) { call -> toBoolean(irCall(call, intrinsics.jsBitXor, dispatchReceiverAsArgument = true)) }
add(it, OperatorNames.AND) { call -> toBoolean(irCall(call, intrinsics.jsBitAnd, receiversAsArguments = true)) }
add(it, OperatorNames.OR) { call -> toBoolean(irCall(call, intrinsics.jsBitOr, receiversAsArguments = true)) }
add(it, OperatorNames.XOR) { call -> toBoolean(irCall(call, intrinsics.jsBitXor, receiversAsArguments = true)) }
add(it, OperatorNames.NOT, intrinsics.jsNot)
}
@@ -88,9 +88,9 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
return with(call.symbol.owner.valueParameters[0].type) {
when {
isByte() || isShort() || isInt() ->
irCall(call, intrinsics.jsNumberRangeToNumber, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsNumberRangeToNumber, receiversAsArguments = true)
isLong() ->
irCall(call, intrinsics.jsNumberRangeToLong, dispatchReceiverAsArgument = true)
irCall(call, intrinsics.jsNumberRangeToLong, receiversAsArguments = true)
else -> call
}
}
@@ -101,7 +101,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
intrinsic: IrFunctionSymbol,
toInt32: Boolean = false
): IrExpression {
val newCall = irCall(call, intrinsic, dispatchReceiverAsArgument = true)
val newCall = irCall(call, intrinsic, receiversAsArguments = true)
if (toInt32)
return toInt32(newCall)
return newCall
@@ -152,7 +152,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
transformCrement(call, intrinsics.jsMinus)
private fun transformCrement(call: IrFunctionAccessExpression, correspondingBinaryOp: IrFunctionSymbol): IrExpression {
val operation = irCall(call, correspondingBinaryOp, dispatchReceiverAsArgument = true).apply {
val operation = irCall(call, correspondingBinaryOp, receiversAsArguments = true).apply {
putValueArgument(1, buildInt(1))
}
@@ -161,7 +161,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
private fun transformUnaryMinus(call: IrFunctionAccessExpression) =
convertResultToPrimitiveType(
irCall(call, intrinsics.jsUnaryMinus, dispatchReceiverAsArgument = true),
irCall(call, intrinsics.jsUnaryMinus, receiversAsArguments = true),
call.type
)
@@ -9,37 +9,29 @@ import org.jetbrains.kotlin.backend.common.deepCopyWithWrappedDescriptors
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.lower.createStaticFunctionWithReceivers
import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.setSourceRange
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.*
class JvmDeclarationFactory(
@@ -205,7 +205,7 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl
if (superCallee.isDefinitelyNotDefaultImplsMethod()) return super.visitCall(expression)
val redirectTarget = context.declarationFactory.getDefaultImplsFunction(superCallee)
val newCall = irCall(expression, redirectTarget, dispatchReceiverAsArgument = true, extensionReceiverAsArgument = true)
val newCall = irCall(expression, redirectTarget, receiversAsArguments = true)
return super.visitCall(newCall)
}
@@ -6,36 +6,27 @@
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.IrReturn
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
internal val interfacePhase = makeIrFilePhase(
::InterfaceLowering,
@@ -127,7 +118,7 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
val newFunction = removedFunctions[expression.symbol]?.owner
return super.visitCall(
if (newFunction != null) {
irCall(expression, newFunction, dispatchReceiverAsArgument = true, extensionReceiverAsArgument = true)
irCall(expression, newFunction, receiversAsArguments = true)
} else {
expression
}
@@ -148,7 +139,7 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
typeArgumentsCount,
origin
).apply {
copyTypeAndValueArgumentsFrom(expression, dispatchReceiverAsArgument = true, extensionReceiverAsArgument = true)
copyTypeAndValueArgumentsFrom(expression, receiversAsArguments = true)
}
}
} else {
@@ -157,56 +148,3 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
)
}
}
internal fun createStaticFunctionWithReceivers(
irParent: IrDeclarationParent,
name: Name,
oldFunction: IrFunction,
dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type,
origin: IrDeclarationOrigin = oldFunction.origin
): IrSimpleFunction {
val descriptor = WrappedSimpleFunctionDescriptor(Annotations.EMPTY, oldFunction.descriptor.source)
return IrFunctionImpl(
oldFunction.startOffset, oldFunction.endOffset,
origin,
IrSimpleFunctionSymbolImpl(descriptor),
name,
oldFunction.visibility,
Modality.FINAL,
oldFunction.returnType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false
).apply {
descriptor.bind(this)
parent = irParent
copyTypeParametersFrom(oldFunction)
annotations.addAll(oldFunction.annotations)
var offset = 0
val dispatchReceiver = oldFunction.dispatchReceiverParameter?.copyTo(
this,
name = Name.identifier("this"),
index = offset++,
type = dispatchReceiverType!!
)
val extensionReceiver = oldFunction.extensionReceiverParameter?.copyTo(
this,
name = Name.identifier("receiver"),
index = offset++
)
valueParameters.addAll(listOfNotNull(dispatchReceiver, extensionReceiver) +
oldFunction.valueParameters.map { it.copyTo(this, index = it.index + offset) }
)
val mapping: Map<IrValueParameter, IrValueParameter> =
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
.zip(valueParameters).toMap()
body = oldFunction.body
?.transform(VariableRemapper(mapping), null)
?.patchDeclarationParents(this)
metadata = oldFunction.metadata
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -414,23 +414,23 @@ fun ReferenceSymbolTable.referenceFunction(callable: CallableDescriptor): IrFunc
/**
* Create new call based on given [call] and [newFunction]
* [dispatchReceiverAsFirstArgument]: optionally convert call with dispatch receiver to static call
* [firstArgumentAsDispatchReceiver]: optionally convert static call to call with dispatch receiver
* [receiversAsArguments]: optionally convert call with dispatch receiver to static call
* [argumentsAsReceivers]: optionally convert static call to call with dispatch receiver
*/
fun irConstructorCall(
call: IrFunctionAccessExpression,
newFunction: IrConstructor,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
): IrConstructorCall =
irConstructorCall(call, newFunction.symbol, dispatchReceiverAsFirstArgument, firstArgumentAsDispatchReceiver)
irConstructorCall(call, newFunction.symbol, receiversAsArguments, argumentsAsReceivers)
fun irConstructorCall(
call: IrFunctionAccessExpression,
newSymbol: IrConstructorSymbol,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
receiversAsArguments: Boolean = false,
argumentsAsDispatchers: Boolean = false
): IrConstructorCall =
call.run {
IrConstructorCallImpl(
@@ -446,8 +446,8 @@ fun irConstructorCall(
).apply {
copyTypeAndValueArgumentsFrom(
call,
dispatchReceiverAsFirstArgument,
firstArgumentAsDispatchReceiver
receiversAsArguments,
argumentsAsDispatchers
)
}
}
@@ -455,27 +455,21 @@ fun irConstructorCall(
fun irCall(
call: IrFunctionAccessExpression,
newFunction: IrFunction,
dispatchReceiverAsArgument: Boolean = false,
argumentAsDispatchReceiver: Boolean = false,
extensionReceiverAsArgument: Boolean = false,
argumentAsExtensionReceiver: Boolean = false
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
): IrCall =
irCall(
call,
newFunction.symbol,
dispatchReceiverAsArgument,
argumentAsDispatchReceiver,
extensionReceiverAsArgument,
argumentAsExtensionReceiver
receiversAsArguments,
argumentsAsReceivers
)
fun irCall(
call: IrFunctionAccessExpression,
newSymbol: IrFunctionSymbol,
dispatchReceiverAsArgument: Boolean = false,
argumentAsDispatchReceiver: Boolean = false,
extensionReceiverAsArgument: Boolean = false,
argumentAsExtensionReceiver: Boolean = false
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
): IrCall =
call.run {
IrCallImpl(
@@ -489,54 +483,42 @@ fun irCall(
).apply {
copyTypeAndValueArgumentsFrom(
call,
dispatchReceiverAsArgument,
argumentAsDispatchReceiver,
extensionReceiverAsArgument,
argumentAsExtensionReceiver
receiversAsArguments,
argumentsAsReceivers
)
}
}
fun IrFunctionAccessExpression.copyTypeAndValueArgumentsFrom(
src: IrFunctionAccessExpression,
dispatchReceiverAsArgument: Boolean = false,
argumentAsDispatchReceiver: Boolean = false,
extensionReceiverAsArgument: Boolean = false,
argumentAsExtensionReceiver: Boolean = false
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
) = copyTypeAndValueArgumentsFrom(
src,
src.symbol.owner,
symbol.owner,
dispatchReceiverAsArgument,
argumentAsDispatchReceiver,
extensionReceiverAsArgument,
argumentAsExtensionReceiver
receiversAsArguments,
argumentsAsReceivers
)
fun IrFunctionReference.copyTypeAndValueArgumentsFrom(
src: IrFunctionReference,
dispatchReceiverAsArgument: Boolean = false,
argumentAsDispatchReceiver: Boolean = false,
extensionReceiverAsArgument: Boolean = false,
argumentAsExtensionReceiver: Boolean = false
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
) = copyTypeAndValueArgumentsFrom(
src,
src.symbol.owner,
symbol.owner,
dispatchReceiverAsArgument,
argumentAsDispatchReceiver,
extensionReceiverAsArgument,
argumentAsExtensionReceiver
receiversAsArguments,
argumentsAsReceivers
)
private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom(
src: IrMemberAccessExpression,
srcFunction: IrFunction,
destFunction: IrFunction,
dispatchReceiverAsArgument: Boolean = false,
argumentAsDispatchReceiver: Boolean = false,
extensionReceiverAsArgument: Boolean = false,
argumentAsExtensionReceiver: Boolean = false
receiversAsArguments: Boolean = false,
argumentsAsReceivers: Boolean = false
) {
copyTypeArgumentsFrom(src)
@@ -544,10 +526,10 @@ private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom(
var srcValueArgumentIndex = 0
when {
dispatchReceiverAsArgument && srcFunction.dispatchReceiverParameter != null -> {
receiversAsArguments && srcFunction.dispatchReceiverParameter != null -> {
putValueArgument(destValueArgumentIndex++, src.dispatchReceiver)
}
argumentAsDispatchReceiver && destFunction.dispatchReceiverParameter != null -> {
argumentsAsReceivers && destFunction.dispatchReceiverParameter != null -> {
dispatchReceiver = src.getValueArgument(srcValueArgumentIndex++)
}
else -> {
@@ -556,10 +538,10 @@ private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom(
}
when {
extensionReceiverAsArgument && srcFunction.extensionReceiverParameter != null -> {
receiversAsArguments && srcFunction.extensionReceiverParameter != null -> {
putValueArgument(destValueArgumentIndex++, src.extensionReceiver)
}
argumentAsExtensionReceiver && destFunction.extensionReceiverParameter != null -> {
argumentsAsReceivers && destFunction.extensionReceiverParameter != null -> {
extensionReceiver = src.getValueArgument(srcValueArgumentIndex++)
}
else -> {