[IR] Unify MFVC bridge redirection, fix related bugs, support MFVC overriding functions with default parameters

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2023-04-22 08:44:09 +02:00
committed by Space Team
parent 384ed9cc9e
commit bf5fa61ffb
28 changed files with 577 additions and 433 deletions
@@ -5,11 +5,10 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedString
import org.jetbrains.kotlin.backend.common.ir.ValueRemapper
import org.jetbrains.kotlin.backend.common.lower.isMovedReceiver
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.memoryOptimizedPlus
import org.jetbrains.kotlin.backend.common.lower.isMovedReceiver as isMovedReceiverImpl
// TODO: fix expect/actual default parameters
@@ -263,8 +263,11 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
protected val forceSetOverrideSymbols: Boolean = true,
) : IrElementTransformerVoid(), BodyLoweringPass {
private val declarationStack = mutableListOf<IrDeclaration>()
override fun lower(irBody: IrBody, container: IrDeclaration) {
declarationStack.push(container)
irBody.transformChildrenVoid(this)
declarationStack.pop()
}
protected open fun shouldReplaceWithSyntheticFunction(functionAccess: IrFunctionAccessExpression): Boolean {
@@ -275,50 +278,44 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
if (!shouldReplaceWithSyntheticFunction(expression))
return expression
val (symbol, params) = parametersForCall(expression) ?: return expression
val symbol = createStubFunction(expression) ?: return expression
for (i in 0 until expression.typeArgumentsCount) {
log { "$symbol[$i]: ${expression.getTypeArgument(i)}" }
}
symbol.owner.typeParameters.forEach { log { "${symbol.owner}[${it.index}] : $it" } }
val stubFunction = symbol.owner
stubFunction.typeParameters.forEach { log { "$stubFunction[${it.index}] : $it" } }
val isStatic = isStatic(expression.symbol.owner)
val newCall = builder(symbol).apply {
copyTypeArgumentsFrom(expression)
var receivers = 0
if (isStatic) {
if (symbol.owner.dispatchReceiverParameter != null) {
dispatchReceiver = params[receivers++]
val declaration = expression.symbol.owner
val currentDeclaration = declarationStack.last()
return context.createIrBuilder(
currentDeclaration.symbol, startOffset = expression.startOffset, endOffset = expression.endOffset
).irBlock {
val newCall = builder(symbol).apply {
val offset = if (needsTypeArgumentOffset(declaration)) declaration.parentAsClass.typeParameters.size else 0
for (i in 0 until typeArgumentsCount) {
putTypeArgument(i, expression.getTypeArgument(i + offset))
}
if (symbol.owner.extensionReceiverParameter != null) {
extensionReceiver = params[receivers++]
val parameter2arguments = argumentsForCall(expression, stubFunction)
for ((parameter, argument) in parameter2arguments) {
when (parameter) {
stubFunction.dispatchReceiverParameter -> log { "call::dispatch@: ${ir2string(argument)}" }
stubFunction.extensionReceiverParameter -> log { "call::extension@: ${ir2string(argument)}" }
else -> log { "call::params@$${parameter.index}/${parameter.name}: ${ir2string(argument)}" }
}
if (argument != null) {
putArgument(parameter, argument)
}
}
} else {
dispatchReceiver = expression.dispatchReceiver
extensionReceiver = expression.extensionReceiver
}
params.drop(receivers).forEachIndexed { i, value ->
log { "call::params@$i/${symbol.owner.valueParameters[i].name}: ${ir2string(value)}" }
putValueArgument(i, value)
}
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
}
return newCall.takeIf { it.type == expression.type } ?: IrTypeOperatorCallImpl(
startOffset = newCall.startOffset,
endOffset = newCall.endOffset,
type = expression.type,
operator = IrTypeOperator.IMPLICIT_CAST,
typeOperand = expression.type,
argument = newCall
)
+irCastIfNeeded(newCall, expression.type)
}.unwrapBlock()
}
private fun needsTypeArgumentOffset(declaration: IrFunction) =
isStatic(declaration) && declaration.parentAsClass.isMultiFieldValueClass && declaration is IrSimpleFunction
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
expression.transformChildrenVoid()
return visitFunctionAccessExpression(expression) {
@@ -362,11 +359,13 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid()
val declaration = expression.symbol.owner
val typeParametersToRemove = if (needsTypeArgumentOffset(declaration)) declaration.parentAsClass.typeParameters.size else 0
with(expression) {
return visitFunctionAccessExpression(expression) {
IrCallImpl(
startOffset, endOffset, (it as IrSimpleFunctionSymbol).owner.returnType, it,
typeArgumentsCount = typeArgumentsCount,
typeArgumentsCount = typeArgumentsCount - typeParametersToRemove,
valueArgumentsCount = it.owner.valueParameters.size,
origin = LoweredStatementOrigins.DEFAULT_DISPATCH_CALL,
superQualifierSymbol = superQualifierSymbol
@@ -375,9 +374,7 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
}
}
open protected fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
val startOffset = expression.startOffset
val endOffset = expression.endOffset
private fun createStubFunction(expression: IrFunctionAccessExpression): IrFunctionSymbol? {
val declaration = expression.symbol.owner
// We *have* to find the actual function here since on the JVM, a default stub for a function implemented
@@ -396,8 +393,14 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
baseFunction.copyAnnotations(),
)
} ?: return null
log { "$declaration -> $stubFunction" }
return stubFunction.symbol
}
protected open fun IrBlockBuilder.argumentsForCall(expression: IrFunctionAccessExpression, stubFunction: IrFunction): Map<IrValueParameter, IrExpression?> {
val startOffset = expression.startOffset
val endOffset = expression.endOffset
val declaration = expression.symbol.owner
val realArgumentsNumber = declaration.valueParameters.filterNot { it.isMovedReceiver() }.size
val maskValues = IntArray((realArgumentsNumber + 31) / 32)
@@ -408,32 +411,48 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
}
var sourceParameterIndex = -1
val valueParametersPrefix =
if (isStatic(declaration))
return buildMap {
val valueParametersPrefix: List<IrValueParameter> = if (isStatic(declaration)) {
listOfNotNull(stubFunction.dispatchReceiverParameter, stubFunction.extensionReceiverParameter)
else emptyList()
return stubFunction.symbol to (valueParametersPrefix + stubFunction.valueParameters).mapIndexed { i, parameter ->
if (!parameter.isMovedReceiver() && parameter != stubFunction.dispatchReceiverParameter && parameter != stubFunction.extensionReceiverParameter) {
++sourceParameterIndex
} else {
stubFunction.dispatchReceiverParameter?.let { put(it, expression.dispatchReceiver) }
stubFunction.extensionReceiverParameter?.let { put(it, expression.extensionReceiver) }
listOf()
}
when {
sourceParameterIndex >= realArgumentsNumber + maskValues.size -> IrConstImpl.constNull(startOffset, endOffset, parameter.type)
sourceParameterIndex >= realArgumentsNumber -> IrConstImpl.int(startOffset, endOffset, parameter.type, maskValues[sourceParameterIndex - realArgumentsNumber])
else -> {
val valueArgument = expression.getValueArgument(i)
if (valueArgument == null) {
maskValues[sourceParameterIndex / 32] = maskValues[sourceParameterIndex / 32] or (1 shl (sourceParameterIndex % 32))
}
valueArgument ?: nullConst(startOffset, endOffset, parameter)?.let {
IrCompositeImpl(
expression.startOffset,
expression.endOffset,
parameter.type,
IrStatementOrigin.DEFAULT_VALUE,
listOf(it)
)
for ((i, parameter) in (valueParametersPrefix + stubFunction.valueParameters).withIndex()) {
if (!parameter.isMovedReceiver() && parameter != stubFunction.dispatchReceiverParameter && parameter != stubFunction.extensionReceiverParameter) {
++sourceParameterIndex
}
val newArgument = when {
sourceParameterIndex >= realArgumentsNumber + maskValues.size -> IrConstImpl.constNull(
startOffset,
endOffset,
parameter.type
)
sourceParameterIndex >= realArgumentsNumber -> IrConstImpl.int(
startOffset,
endOffset,
parameter.type,
maskValues[sourceParameterIndex - realArgumentsNumber]
)
else -> {
val valueArgument = expression.getValueArgument(i)
if (valueArgument == null) {
maskValues[sourceParameterIndex / 32] =
maskValues[sourceParameterIndex / 32] or (1 shl (sourceParameterIndex % 32))
}
valueArgument ?: nullConst(startOffset, endOffset, parameter)?.let {
IrCompositeImpl(
expression.startOffset,
expression.endOffset,
parameter.type,
IrStatementOrigin.DEFAULT_VALUE,
listOf(it)
)
}
}
}
put(parameter, newArgument)
}
}
}
@@ -455,6 +474,8 @@ open class DefaultParameterInjector<TContext : CommonBackendContext>(
protected open fun isStatic(function: IrFunction): Boolean = false
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
protected fun IrValueParameter.isMovedReceiver() = isMovedReceiverImpl()
}
// Remove default argument initializers.
@@ -374,6 +374,7 @@ class InlineClassLowering(val context: CommonBackendContext) {
function.parent,
function.toInlineClassImplementationName(),
function,
typeParametersFromContext = extractTypeParameters(function.parentAsClass)
typeParametersFromContext = extractTypeParameters(function.parentAsClass),
remapMultiFieldValueClassStructure = context::remapMultiFieldValueClassStructure
)
}