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:
committed by
max-kammerer
parent
1abdf0561a
commit
969478481e
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+15
-51
@@ -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)
|
||||
}
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
-1
@@ -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
|
||||
|
||||
+5
-5
@@ -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
|
||||
|
||||
-1
@@ -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
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
+8
-8
@@ -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
|
||||
)
|
||||
|
||||
|
||||
+4
-12
@@ -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(
|
||||
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
|
||||
+2
-64
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -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 -> {
|
||||
|
||||
Reference in New Issue
Block a user