IR: refactor DefaultParameterInjector

This commit is contained in:
pyos
2019-11-13 10:57:31 +01:00
committed by Georgy Bronnikov
parent 7a2715da44
commit 2b2dd097a3
@@ -181,15 +181,9 @@ open class DefaultArgumentStubGenerator(
private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" } private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" }
} }
private fun maskParameterDeclaration(function: IrFunction, number: Int) =
maskParameter(function, number)
private fun maskParameter(function: IrFunction, number: Int) = private fun maskParameter(function: IrFunction, number: Int) =
function.valueParameters.single { it.name == parameterMaskName(number) } function.valueParameters.single { it.name == parameterMaskName(number) }
private fun markerParameterDeclaration(function: IrFunction) =
function.valueParameters.single { it.name == kConstructorMarkerName }
val DEFAULT_DISPATCH_CALL = object : IrStatementOriginImpl("DEFAULT_DISPATCH_CALL") {} val DEFAULT_DISPATCH_CALL = object : IrStatementOriginImpl("DEFAULT_DISPATCH_CALL") {}
open class DefaultParameterInjector( open class DefaultParameterInjector(
@@ -206,29 +200,23 @@ open class DefaultParameterInjector(
irBody.transformChildrenVoid(this) irBody.transformChildrenVoid(this)
} }
private fun visitFunctionAccessExpression( private fun <T : IrFunctionAccessExpression> visitFunctionAccessExpression(expression: T, builder: (IrFunctionSymbol) -> T): T {
expression: IrFunctionAccessExpression,
builder: (IrFunctionSymbol) -> IrFunctionAccessExpression
): IrExpression {
val argumentsCount = (0 until expression.valueArgumentsCount).count { expression.getValueArgument(it) != null } val argumentsCount = (0 until expression.valueArgumentsCount).count { expression.getValueArgument(it) != null }
if (argumentsCount == expression.symbol.owner.valueParameters.size) if (argumentsCount == expression.symbol.owner.valueParameters.size)
return expression return expression
val (symbol, params) = parametersForCall(expression) ?: return expression val (symbol, params) = parametersForCall(expression) ?: return expression
val descriptor = symbol.descriptor
val declaration = symbol.owner
for (i in 0 until expression.typeArgumentsCount) { for (i in 0 until expression.typeArgumentsCount) {
log { "$descriptor [$i]: $expression.getTypeArgument(i)" } log { "${symbol.descriptor}[$i]: ${expression.getTypeArgument(i)}" }
} }
declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } } symbol.owner.typeParameters.forEach { log { "${symbol.owner}[${it.index}] : $it" } }
return builder(symbol).apply { return builder(symbol).apply {
this.copyTypeArgumentsFrom(expression) copyTypeArgumentsFrom(expression)
params.forEach { params.forEachIndexed { i, value ->
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } log { "call::params@$i/${symbol.owner.valueParameters[i].name}: ${ir2string(value)}" }
putValueArgument(it.first.index, it.second) putValueArgument(i, value)
} }
dispatchReceiver = expression.dispatchReceiver dispatchReceiver = expression.dispatchReceiver
@@ -240,106 +228,73 @@ open class DefaultParameterInjector(
} }
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
super.visitDelegatingConstructorCall(expression) expression.transformChildrenVoid()
return visitFunctionAccessExpression(expression) { return visitFunctionAccessExpression(expression) {
IrDelegatingConstructorCallImpl( with(expression) {
startOffset = expression.startOffset, IrDelegatingConstructorCallImpl(startOffset, endOffset, type, it as IrConstructorSymbol, typeArgumentsCount)
endOffset = expression.endOffset, }
type = context.irBuiltIns.unitType,
symbol = it as IrConstructorSymbol,
typeArgumentsCount = expression.typeArgumentsCount
)
} }
} }
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
super.visitConstructorCall(expression) expression.transformChildrenVoid()
return visitFunctionAccessExpression(expression) { return visitFunctionAccessExpression(expression) {
IrConstructorCallImpl.fromSymbolOwner( with(expression) {
expression.startOffset, IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, it as IrConstructorSymbol, DEFAULT_DISPATCH_CALL)
expression.endOffset, }
expression.type,
it as IrConstructorSymbol,
it.owner.parentAsClass.typeParameters.size,
DEFAULT_DISPATCH_CALL
)
} }
} }
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression { override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
super.visitEnumConstructorCall(expression) expression.transformChildrenVoid()
return visitFunctionAccessExpression(expression) { return visitFunctionAccessExpression(expression) {
IrEnumConstructorCallImpl( with(expression) {
expression.startOffset, IrEnumConstructorCallImpl(startOffset, endOffset, type, it as IrConstructorSymbol)
expression.endOffset, }
expression.type,
it as IrConstructorSymbol
)
} }
} }
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall): IrExpression {
super.visitCall(expression) expression.transformChildrenVoid()
return visitFunctionAccessExpression(expression) { return visitFunctionAccessExpression(expression) {
IrCallImpl( with(expression) {
startOffset = expression.startOffset, IrCallImpl(startOffset, endOffset, type, it, typeArgumentsCount, DEFAULT_DISPATCH_CALL, superQualifierSymbol)
endOffset = expression.endOffset, }
type = expression.type,
symbol = it,
typeArgumentsCount = expression.typeArgumentsCount,
origin = DEFAULT_DISPATCH_CALL,
superQualifierSymbol = expression.superQualifierSymbol
)
} }
} }
private fun parametersForCall( private fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<IrExpression?>>? {
expression: IrFunctionAccessExpression
): Pair<IrFunctionSymbol, List<Pair<IrValueParameter, IrExpression?>>>? {
val declaration = expression.symbol.owner
val keyFunction = declaration.generateDefaultsFunction(context, skipInline, skipExternalMethods) ?: return null
val realFunction = if (keyFunction is IrSimpleFunction) keyFunction.resolveFakeOverride()!! else keyFunction
log { "$declaration -> $realFunction" }
val maskValues = Array((declaration.valueParameters.size + 31) / 32) { 0 }
val params = mutableListOf<Pair<IrValueParameter, IrExpression?>>()
params += declaration.valueParameters.mapIndexed { argIndex, _ ->
val valueArgument = expression.getValueArgument(argIndex)
if (valueArgument == null) {
val maskIndex = argIndex / 32
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (argIndex % 32))
}
val valueParameterDeclaration = realFunction.valueParameters[argIndex]
val defaultValueArgument = nullConst(expression.startOffset, expression.endOffset, valueParameterDeclaration)
valueParameterDeclaration to (valueArgument ?: defaultValueArgument)
}
val startOffset = expression.startOffset val startOffset = expression.startOffset
val endOffset = expression.endOffset val endOffset = expression.endOffset
maskValues.forEachIndexed { i, maskValue -> val declaration = expression.symbol.owner
params += maskParameterDeclaration(realFunction, i) to IrConstImpl.int(
startOffset = startOffset, val stubOverride = declaration.generateDefaultsFunction(context, skipInline, skipExternalMethods) ?: return null
endOffset = endOffset, // We *have* to resolve the fake override here since on the JVM, a default stub for a function implemented
type = context.irBuiltIns.intType, // in an interface does not leave an abstract method after being moved to DefaultImpls (see InterfaceLowering).
value = maskValue // Calling the fake override on an implementation of that interface would then result in a call to a method
) // that does not actually exist as DefaultImpls is not part of the inheritance hierarchy.
val stubFunction = if (stubOverride is IrSimpleFunction) stubOverride.resolveFakeOverride()!! else stubOverride
log { "$declaration -> $stubFunction" }
val realArgumentsNumber = declaration.valueParameters.size
val maskValues = IntArray((declaration.valueParameters.size + 31) / 32)
assert((stubFunction.valueParameters.size - realArgumentsNumber - maskValues.size) in listOf(0, 1)) {
"argument count mismatch: expected $realArgumentsNumber arguments + ${maskValues.size} masks + optional handler/marker, " +
"got ${stubFunction.valueParameters.size} total in ${stubFunction.render()}"
} }
if (expression.symbol is IrConstructorSymbol) { return stubFunction.symbol to stubFunction.valueParameters.mapIndexed { i, parameter ->
val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker when {
params += markerParameterDeclaration(realFunction) to i >= realArgumentsNumber + maskValues.size -> IrConstImpl.constNull(startOffset, endOffset, parameter.type)
IrConstImpl.constNull(startOffset, endOffset, defaultArgumentMarker.owner.defaultType.makeNullable()) i >= realArgumentsNumber -> IrConstImpl.int(startOffset, endOffset, parameter.type, maskValues[i - realArgumentsNumber])
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { else -> {
params += realFunction.valueParameters.last() to val valueArgument = expression.getValueArgument(i)
IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType) if (valueArgument == null) {
maskValues[i / 32] = maskValues[i / 32] or (1 shl (i % 32))
}
valueArgument ?: nullConst(startOffset, endOffset, parameter)
}
}
} }
params.forEach {
log { "descriptor::${realFunction.name.asString()}#${it.first.index}: ${it.first.name.asString()}" }
}
return Pair(realFunction.symbol, params)
} }
protected open fun nullConst(startOffset: Int, endOffset: Int, irParameter: IrValueParameter): IrExpression? = protected open fun nullConst(startOffset: Int, endOffset: Int, irParameter: IrValueParameter): IrExpression? =
@@ -426,10 +381,8 @@ private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContex
newFunction.addValueParameter(parameterMaskName(i).asString(), context.irBuiltIns.intType) newFunction.addValueParameter(parameterMaskName(i).asString(), context.irBuiltIns.intType)
} }
if (this is IrConstructor) { if (this is IrConstructor) {
newFunction.addValueParameter( val markerType = context.ir.symbols.defaultConstructorMarker.owner.defaultType.makeNullable()
kConstructorMarkerName.asString(), newFunction.addValueParameter("marker".synthesizedString, markerType)
context.ir.symbols.defaultConstructorMarker.owner.defaultType.makeNullable()
)
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
newFunction.addValueParameter("handler".synthesizedString, context.irBuiltIns.anyNType) newFunction.addValueParameter("handler".synthesizedString, context.irBuiltIns.anyNType)
} }
@@ -439,6 +392,4 @@ private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContex
newFunction newFunction
} }
internal val kConstructorMarkerName = "marker".synthesizedName
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName private fun parameterMaskName(number: Int) = "mask$number".synthesizedName