[IR] Unify MFVC bridge redirection, fix related bugs, support MFVC overriding functions with default parameters
#KT-1179
This commit is contained in:
committed by
Space Team
parent
384ed9cc9e
commit
bf5fa61ffb
+85
-64
@@ -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.
|
||||
|
||||
+2
-1
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user