JVM_IR: use DefaultParameterInjector
This commit is contained in:
+7
@@ -975,6 +975,13 @@ open class WrappedFieldDescriptor(
|
|||||||
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
|
override fun <V : Any?> getUserData(key: CallableDescriptor.UserDataKey<V>?): V? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun wrappedSimpleFunctionDescriptorBasedOn(descriptor: SimpleFunctionDescriptor) =
|
||||||
|
if (descriptor is DescriptorWithContainerSource)
|
||||||
|
// TODO: Do we ever need annotations and source for these?
|
||||||
|
WrappedFunctionDescriptorWithContainerSource(descriptor.containerSource)
|
||||||
|
else
|
||||||
|
WrappedSimpleFunctionDescriptor(descriptor.annotations, descriptor.source)
|
||||||
|
|
||||||
private fun getContainingDeclaration(declaration: IrDeclarationWithName): DeclarationDescriptor {
|
private fun getContainingDeclaration(declaration: IrDeclarationWithName): DeclarationDescriptor {
|
||||||
val parent = declaration.parent
|
val parent = declaration.parent
|
||||||
return if (parent is IrClass && parent.origin == IrDeclarationOrigin.FILE_CLASS && parent.parent is IrExternalPackageFragment) {
|
return if (parent is IrClass && parent.origin == IrDeclarationOrigin.FILE_CLASS && parent.parent is IrExternalPackageFragment) {
|
||||||
|
|||||||
@@ -549,15 +549,23 @@ fun createStaticFunctionWithReceivers(
|
|||||||
oldFunction.valueParameters.map { it.copyTo(this, index = it.index + offset) }
|
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) {
|
if (copyBody) {
|
||||||
body = oldFunction.body
|
copyBodyToStatic(oldFunction, this)
|
||||||
?.transform(VariableRemapper(mapping), null)
|
|
||||||
?.patchDeclarationParents(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata = oldFunction.metadata
|
metadata = oldFunction.metadata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun copyBodyToStatic(oldFunction: IrFunction, staticFunction: IrFunction) {
|
||||||
|
val mapping: Map<IrValueParameter, IrValueParameter> =
|
||||||
|
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
|
||||||
|
.zip(staticFunction.valueParameters).toMap()
|
||||||
|
staticFunction.body = oldFunction.body
|
||||||
|
?.transform(VariableRemapper(mapping), null)
|
||||||
|
?.patchDeclarationParents(staticFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrClass.underlyingType() = if (isInline)
|
||||||
|
constructors.single { it.isPrimary }.valueParameters[0].type
|
||||||
|
else defaultType
|
||||||
|
|||||||
+233
-176
@@ -5,19 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.lower
|
package org.jetbrains.kotlin.backend.common.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.ir.*
|
||||||
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDescriptor
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
@@ -25,8 +17,10 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
@@ -37,6 +31,7 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
// TODO: fix expect/actual default parameters
|
// TODO: fix expect/actual default parameters
|
||||||
|
|
||||||
@@ -206,173 +201,202 @@ private fun markerParameterDeclaration(function: IrFunction) =
|
|||||||
val DEFAULT_DISPATCH_CALL = object : IrStatementOriginImpl("DEFAULT_DISPATCH_CALL") {}
|
val DEFAULT_DISPATCH_CALL = object : IrStatementOriginImpl("DEFAULT_DISPATCH_CALL") {}
|
||||||
|
|
||||||
open class DefaultParameterInjector(
|
open class DefaultParameterInjector(
|
||||||
val context: CommonBackendContext,
|
open val context: CommonBackendContext,
|
||||||
private val skipInline: Boolean = true,
|
private val skipInline: Boolean = true,
|
||||||
private val skipExternalMethods: Boolean = false
|
private val skipExternalMethods: Boolean = false,
|
||||||
) : FileLoweringPass {
|
private val shiftMaskForExtraArgs: Boolean = false
|
||||||
|
) : IrElementTransformerVoid(), BodyLoweringPass, FileLoweringPass {
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
irFile.transformChildrenVoid(this)
|
||||||
private fun visitFunctionAccessExpression(
|
|
||||||
expression: IrFunctionAccessExpression,
|
|
||||||
builder: (IrFunctionSymbol) -> IrFunctionAccessExpression
|
|
||||||
): IrExpression {
|
|
||||||
val functionDeclaration = expression.symbol.owner
|
|
||||||
|
|
||||||
if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
|
|
||||||
return expression
|
|
||||||
|
|
||||||
val argumentsCount = argumentCount(expression)
|
|
||||||
if (argumentsCount == functionDeclaration.valueParameters.size)
|
|
||||||
return expression
|
|
||||||
|
|
||||||
val (symbol, params) = parametersForCall(expression)
|
|
||||||
val descriptor = symbol.descriptor
|
|
||||||
val declaration = symbol.owner
|
|
||||||
|
|
||||||
for (i in 0 until expression.typeArgumentsCount) {
|
|
||||||
log { "$descriptor [$i]: $expression.getTypeArgument(i)" }
|
|
||||||
}
|
|
||||||
declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } }
|
|
||||||
|
|
||||||
return builder(symbol).apply {
|
|
||||||
this.copyTypeArgumentsFrom(expression)
|
|
||||||
|
|
||||||
params.forEach {
|
|
||||||
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
|
|
||||||
putValueArgument(it.first.index, it.second)
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchReceiver = expression.dispatchReceiver
|
|
||||||
extensionReceiver = expression.extensionReceiver
|
|
||||||
|
|
||||||
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
|
|
||||||
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
|
||||||
super.visitDelegatingConstructorCall(expression)
|
|
||||||
|
|
||||||
return visitFunctionAccessExpression(expression) {
|
|
||||||
IrDelegatingConstructorCallImpl(
|
|
||||||
startOffset = expression.startOffset,
|
|
||||||
endOffset = expression.endOffset,
|
|
||||||
type = context.irBuiltIns.unitType,
|
|
||||||
symbol = it as IrConstructorSymbol,
|
|
||||||
descriptor = it.descriptor,
|
|
||||||
typeArgumentsCount = expression.typeArgumentsCount
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
|
|
||||||
super.visitConstructorCall(expression)
|
|
||||||
|
|
||||||
return visitFunctionAccessExpression(expression) {
|
|
||||||
IrConstructorCallImpl.fromSymbolOwner(
|
|
||||||
expression.startOffset,
|
|
||||||
expression.endOffset,
|
|
||||||
it.owner.returnType,
|
|
||||||
it as IrConstructorSymbol,
|
|
||||||
DEFAULT_DISPATCH_CALL
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
super.visitCall(expression)
|
|
||||||
|
|
||||||
return visitFunctionAccessExpression(expression) {
|
|
||||||
IrCallImpl(
|
|
||||||
startOffset = expression.startOffset,
|
|
||||||
endOffset = expression.endOffset,
|
|
||||||
type = it.owner.returnType,
|
|
||||||
symbol = it,
|
|
||||||
descriptor = it.descriptor,
|
|
||||||
typeArgumentsCount = expression.typeArgumentsCount,
|
|
||||||
origin = DEFAULT_DISPATCH_CALL,
|
|
||||||
superQualifierSymbol = expression.superQualifierSymbol
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
|
|
||||||
if (!needsDefaultArgumentsLowering(skipInline, skipExternalMethods)) return null
|
|
||||||
|
|
||||||
if (this !is IrSimpleFunction) return this
|
|
||||||
|
|
||||||
for (s in overriddenSymbols) {
|
|
||||||
s.owner.findSuperMethodWithDefaultArguments()?.let { return it }
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<Pair<IrValueParameter, IrExpression?>>> {
|
|
||||||
val declaration = expression.symbol.owner
|
|
||||||
|
|
||||||
val keyFunction = declaration.findSuperMethodWithDefaultArguments()!!
|
|
||||||
val realFunction =
|
|
||||||
keyFunction.generateDefaultsFunction(context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, skipInline, skipExternalMethods)
|
|
||||||
|
|
||||||
log { "$declaration -> $realFunction" }
|
|
||||||
val maskValues = Array((declaration.valueParameters.size + 31) / 32) { 0 }
|
|
||||||
val params = mutableListOf<Pair<IrValueParameter, IrExpression?>>()
|
|
||||||
params += declaration.valueParameters.mapIndexed { i, _ ->
|
|
||||||
val valueArgument = expression.getValueArgument(i)
|
|
||||||
if (valueArgument == null) {
|
|
||||||
val maskIndex = i / 32
|
|
||||||
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32))
|
|
||||||
}
|
|
||||||
val valueParameterDeclaration = realFunction.valueParameters[i]
|
|
||||||
val defaultValueArgument = if (valueParameterDeclaration.varargElementType != null) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
nullConst(expression, realFunction.valueParameters[i].type)
|
|
||||||
}
|
|
||||||
valueParameterDeclaration to (valueArgument ?: defaultValueArgument)
|
|
||||||
}
|
|
||||||
|
|
||||||
val startOffset = expression.startOffset
|
|
||||||
val endOffset = expression.endOffset
|
|
||||||
maskValues.forEachIndexed { i, maskValue ->
|
|
||||||
params += maskParameterDeclaration(realFunction, i) to IrConstImpl.int(
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
type = context.irBuiltIns.intType,
|
|
||||||
value = maskValue
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (expression.symbol is IrConstructorSymbol) {
|
|
||||||
val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker
|
|
||||||
params += markerParameterDeclaration(realFunction) to IrGetObjectValueImpl(
|
|
||||||
startOffset = startOffset,
|
|
||||||
endOffset = endOffset,
|
|
||||||
type = defaultArgumentMarker.owner.defaultType,
|
|
||||||
symbol = defaultArgumentMarker
|
|
||||||
)
|
|
||||||
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
|
||||||
params += realFunction.valueParameters.last() to
|
|
||||||
IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType)
|
|
||||||
}
|
|
||||||
params.forEach {
|
|
||||||
log { "descriptor::${realFunction.name.asString()}#${it.first.index}: ${it.first.name.asString()}" }
|
|
||||||
}
|
|
||||||
return Pair(realFunction.symbol, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun argumentCount(expression: IrMemberAccessExpression): Int {
|
|
||||||
var result = 0
|
|
||||||
for (i in 0 until expression.valueArgumentsCount) {
|
|
||||||
expression.getValueArgument(i)?.run { ++result }
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun nullConst(expression: IrElement, type: IrType) = when {
|
override fun lower(irBody: IrBody) {
|
||||||
|
irBody.transformChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitFunctionAccessExpression(
|
||||||
|
expression: IrFunctionAccessExpression,
|
||||||
|
builder: (IrFunctionSymbol) -> IrFunctionAccessExpression
|
||||||
|
): IrExpression {
|
||||||
|
val functionDeclaration = expression.symbol.owner
|
||||||
|
|
||||||
|
if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
|
||||||
|
return expression
|
||||||
|
|
||||||
|
val argumentsCount = argumentCount(expression)
|
||||||
|
if (argumentsCount == functionDeclaration.valueParameters.size)
|
||||||
|
return expression
|
||||||
|
|
||||||
|
val (symbol, params) = parametersForCall(expression, shiftMaskForExtraArgs)
|
||||||
|
val descriptor = symbol.descriptor
|
||||||
|
val declaration = symbol.owner
|
||||||
|
|
||||||
|
for (i in 0 until expression.typeArgumentsCount) {
|
||||||
|
log { "$descriptor [$i]: $expression.getTypeArgument(i)" }
|
||||||
|
}
|
||||||
|
declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } }
|
||||||
|
|
||||||
|
return builder(symbol).apply {
|
||||||
|
this.copyTypeArgumentsFrom(expression)
|
||||||
|
|
||||||
|
params.forEach {
|
||||||
|
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
|
||||||
|
putValueArgument(it.first.index, it.second)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchReceiver = expression.dispatchReceiver
|
||||||
|
extensionReceiver = expression.extensionReceiver
|
||||||
|
|
||||||
|
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
|
||||||
|
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||||
|
super.visitDelegatingConstructorCall(expression)
|
||||||
|
|
||||||
|
return visitFunctionAccessExpression(expression) {
|
||||||
|
IrDelegatingConstructorCallImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = context.irBuiltIns.unitType,
|
||||||
|
symbol = it as IrConstructorSymbol,
|
||||||
|
descriptor = it.descriptor,
|
||||||
|
typeArgumentsCount = expression.typeArgumentsCount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
|
||||||
|
super.visitConstructorCall(expression)
|
||||||
|
|
||||||
|
return visitFunctionAccessExpression(expression) {
|
||||||
|
IrConstructorCallImpl.fromSymbolOwner(
|
||||||
|
expression.startOffset,
|
||||||
|
expression.endOffset,
|
||||||
|
expression.type,
|
||||||
|
it as IrConstructorSymbol,
|
||||||
|
DEFAULT_DISPATCH_CALL
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
|
||||||
|
super.visitEnumConstructorCall(expression)
|
||||||
|
|
||||||
|
return visitFunctionAccessExpression(expression) {
|
||||||
|
IrEnumConstructorCallImpl(
|
||||||
|
expression.startOffset,
|
||||||
|
expression.endOffset,
|
||||||
|
expression.type,
|
||||||
|
it as IrConstructorSymbol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
super.visitCall(expression)
|
||||||
|
|
||||||
|
return visitFunctionAccessExpression(expression) {
|
||||||
|
IrCallImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
type = expression.type,
|
||||||
|
symbol = it,
|
||||||
|
descriptor = it.descriptor,
|
||||||
|
typeArgumentsCount = expression.typeArgumentsCount,
|
||||||
|
origin = DEFAULT_DISPATCH_CALL,
|
||||||
|
superQualifierSymbol = expression.superQualifierSymbol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
|
||||||
|
if (!needsDefaultArgumentsLowering(skipInline, skipExternalMethods)) return null
|
||||||
|
|
||||||
|
if (this !is IrSimpleFunction) return this
|
||||||
|
|
||||||
|
for (s in overriddenSymbols) {
|
||||||
|
s.owner.findSuperMethodWithDefaultArguments()?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parametersForCall(
|
||||||
|
expression: IrFunctionAccessExpression,
|
||||||
|
shiftMaskForExtraArgs: Boolean
|
||||||
|
): Pair<IrFunctionSymbol, List<Pair<IrValueParameter, IrExpression?>>> {
|
||||||
|
val declaration = expression.symbol.owner
|
||||||
|
|
||||||
|
val extraArgsShift = when {
|
||||||
|
shiftMaskForExtraArgs && declaration is IrConstructor && declaration.parentAsClass.isEnumClass -> 2
|
||||||
|
shiftMaskForExtraArgs && declaration is IrConstructor && declaration.parentAsClass.isInner -> 1 // skip the `$outer` parameter
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val keyFunction = declaration.findSuperMethodWithDefaultArguments()!!
|
||||||
|
val realFunction =
|
||||||
|
keyFunction.generateDefaultsFunction(
|
||||||
|
context,
|
||||||
|
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||||
|
skipInline,
|
||||||
|
skipExternalMethods
|
||||||
|
)
|
||||||
|
|
||||||
|
log { "$declaration -> $realFunction" }
|
||||||
|
val maskValues = Array((declaration.valueParameters.size - extraArgsShift + 31) / 32) { 0 }
|
||||||
|
val params = mutableListOf<Pair<IrValueParameter, IrExpression?>>()
|
||||||
|
params += declaration.valueParameters.mapIndexed { argIndex, _ ->
|
||||||
|
val valueArgument = expression.getValueArgument(argIndex)
|
||||||
|
val shiftedArgIndex = argIndex - extraArgsShift
|
||||||
|
if (valueArgument == null) {
|
||||||
|
val maskIndex = shiftedArgIndex / 32
|
||||||
|
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (shiftedArgIndex % 32))
|
||||||
|
}
|
||||||
|
val valueParameterDeclaration = realFunction.valueParameters[argIndex]
|
||||||
|
val defaultValueArgument = if (valueParameterDeclaration.varargElementType != null) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
nullConst(expression, realFunction.valueParameters[argIndex].type)
|
||||||
|
}
|
||||||
|
valueParameterDeclaration to (valueArgument ?: defaultValueArgument)
|
||||||
|
}
|
||||||
|
|
||||||
|
val startOffset = expression.startOffset
|
||||||
|
val endOffset = expression.endOffset
|
||||||
|
maskValues.forEachIndexed { i, maskValue ->
|
||||||
|
params += maskParameterDeclaration(realFunction, i) to IrConstImpl.int(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
type = context.irBuiltIns.intType,
|
||||||
|
value = maskValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (expression.symbol is IrConstructorSymbol) {
|
||||||
|
val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker
|
||||||
|
params += markerParameterDeclaration(realFunction) to
|
||||||
|
IrConstImpl.constNull(startOffset, endOffset, defaultArgumentMarker.owner.defaultType)
|
||||||
|
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
||||||
|
params += realFunction.valueParameters.last() to
|
||||||
|
IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType)
|
||||||
|
}
|
||||||
|
params.forEach {
|
||||||
|
log { "descriptor::${realFunction.name.asString()}#${it.first.index}: ${it.first.name.asString()}" }
|
||||||
|
}
|
||||||
|
return Pair(realFunction.symbol, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun argumentCount(expression: IrMemberAccessExpression): Int {
|
||||||
|
var result = 0
|
||||||
|
for (i in 0 until expression.valueArgumentsCount) {
|
||||||
|
expression.getValueArgument(i)?.run { ++result }
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun nullConst(expression: IrElement, type: IrType): IrExpression = when {
|
||||||
type.isFloat() -> IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
|
type.isFloat() -> IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
|
||||||
type.isDouble() -> IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
|
type.isDouble() -> IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
|
||||||
type.isBoolean() -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
|
type.isBoolean() -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
|
||||||
@@ -393,6 +417,16 @@ class DefaultParameterCleaner constructor(val context: CommonBackendContext) : F
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some later lowerings produce bodies that need to undergo default parameter injection.
|
||||||
|
fun IrBody.insertCallsToDefaultArgumentStubs(
|
||||||
|
context: CommonBackendContext,
|
||||||
|
skipInline: Boolean = true,
|
||||||
|
skipExternalMethods: Boolean = false,
|
||||||
|
shiftMaskForExtraArgs: Boolean = false
|
||||||
|
) {
|
||||||
|
DefaultParameterInjector(context, skipInline, skipExternalMethods, shiftMaskForExtraArgs).lower(this)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO this implementation is exponential
|
// TODO this implementation is exponential
|
||||||
private fun IrFunction.needsDefaultArgumentsLowering(skipInlineMethods: Boolean, skipExternalMethods: Boolean): Boolean {
|
private fun IrFunction.needsDefaultArgumentsLowering(skipInlineMethods: Boolean, skipExternalMethods: Boolean): Boolean {
|
||||||
if (isInline && skipInlineMethods) return false
|
if (isInline && skipInlineMethods) return false
|
||||||
@@ -434,7 +468,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
newFunction.copyTypeParametersFrom(this)
|
newFunction.copyTypeParametersFrom(this)
|
||||||
val newValueParameters = valueParameters.map { it.copyTo(newFunction) } + syntheticParameters
|
val newValueParameters = valueParameters.map { it.copyMaybeNullableTo(newFunction, context.irBuiltIns) } + syntheticParameters
|
||||||
newValueParameters.forEach {
|
newValueParameters.forEach {
|
||||||
it.defaultValue = null
|
it.defaultValue = null
|
||||||
}
|
}
|
||||||
@@ -485,7 +519,7 @@ private fun buildFunctionDeclaration(irFunction: IrFunction, origin: IrDeclarati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is IrSimpleFunction -> {
|
is IrSimpleFunction -> {
|
||||||
val descriptor = WrappedSimpleFunctionDescriptor(irFunction.descriptor.annotations, irFunction.descriptor.source)
|
val descriptor = wrappedSimpleFunctionDescriptorBasedOn(irFunction.descriptor as SimpleFunctionDescriptor)
|
||||||
val name = Name.identifier("${irFunction.name}\$default")
|
val name = Name.identifier("${irFunction.name}\$default")
|
||||||
|
|
||||||
return IrFunctionImpl(
|
return IrFunctionImpl(
|
||||||
@@ -543,3 +577,26 @@ private fun IrFunction.valueParameter(index: Int, name: Name, type: IrType): IrV
|
|||||||
internal val kConstructorMarkerName = "marker".synthesizedName
|
internal val kConstructorMarkerName = "marker".synthesizedName
|
||||||
|
|
||||||
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName
|
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName
|
||||||
|
|
||||||
|
private fun IrValueParameter.copyMaybeNullableTo(irFunction: IrFunction, irBuiltIns: IrBuiltIns): IrValueParameter {
|
||||||
|
if (defaultValue == null) return copyTo(irFunction)
|
||||||
|
val underlyingType = type.classOrNull?.owner?.underlyingType() ?: type
|
||||||
|
if (underlyingType in irBuiltIns.primitiveIrTypes) return copyTo(irFunction)
|
||||||
|
|
||||||
|
val newType = type.remapTypeParameters(
|
||||||
|
(parent as IrTypeParametersContainer).classIfConstructor,
|
||||||
|
irFunction.classIfConstructor
|
||||||
|
).makeNullable()
|
||||||
|
|
||||||
|
val descriptor = WrappedValueParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source)
|
||||||
|
return IrValueParameterImpl(
|
||||||
|
startOffset, endOffset, origin, IrValueParameterSymbolImpl(descriptor),
|
||||||
|
name, index, newType, varargElementType, isCrossinline, isNoinline
|
||||||
|
).also {
|
||||||
|
descriptor.bind(it)
|
||||||
|
it.parent = irFunction
|
||||||
|
it.defaultValue = null
|
||||||
|
it.annotations.addAll(annotations.map { it.deepCopyWithSymbols() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.IrElement
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
|
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -67,6 +68,8 @@ class JvmBackendContext(
|
|||||||
val suspendLambdaToOriginalFunctionMap = mutableMapOf<IrClass, IrFunction>()
|
val suspendLambdaToOriginalFunctionMap = mutableMapOf<IrClass, IrFunction>()
|
||||||
val continuationClassBuilders = mutableMapOf<IrClass, ClassBuilder>()
|
val continuationClassBuilders = mutableMapOf<IrClass, ClassBuilder>()
|
||||||
|
|
||||||
|
val staticDefaultStubs = mutableMapOf<IrFunctionSymbol, IrFunction>()
|
||||||
|
|
||||||
internal fun getTopLevelClass(fqName: FqName): IrClassSymbol {
|
internal fun getTopLevelClass(fqName: FqName): IrClassSymbol {
|
||||||
val descriptor = state.module.getPackage(fqName.parent()).memberScope.getContributedClassifier(
|
val descriptor = state.module.getPackage(fqName.parent()).memberScope.getContributedClassifier(
|
||||||
fqName.shortName(), NoLookupLocation.FROM_BACKEND
|
fqName.shortName(), NoLookupLocation.FROM_BACKEND
|
||||||
|
|||||||
@@ -91,6 +91,13 @@ private val defaultArgumentStubPhase = makeIrFilePhase<CommonBackendContext>(
|
|||||||
prerequisite = setOf(localDeclarationsPhase)
|
prerequisite = setOf(localDeclarationsPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val defaultArgumentInjectorPhase = makeIrFilePhase(
|
||||||
|
::JvmDefaultParameterInjector,
|
||||||
|
name = "DefaultParameterInjector",
|
||||||
|
description = "Transform calls with default arguments into calls to stubs",
|
||||||
|
prerequisite = setOf(defaultArgumentStubPhase)
|
||||||
|
)
|
||||||
|
|
||||||
private val innerClassesPhase = makeIrFilePhase(
|
private val innerClassesPhase = makeIrFilePhase(
|
||||||
::InnerClassesLowering,
|
::InnerClassesLowering,
|
||||||
name = "InnerClasses",
|
name = "InnerClasses",
|
||||||
@@ -127,10 +134,12 @@ private val jvmFilePhases =
|
|||||||
callableReferencePhase then
|
callableReferencePhase then
|
||||||
localDeclarationsPhase then
|
localDeclarationsPhase then
|
||||||
defaultArgumentStubPhase then
|
defaultArgumentStubPhase then
|
||||||
|
defaultArgumentInjectorPhase then
|
||||||
|
|
||||||
interfacePhase then
|
interfacePhase then
|
||||||
interfaceDelegationPhase then
|
interfaceDelegationPhase then
|
||||||
interfaceSuperCallsPhase then
|
interfaceSuperCallsPhase then
|
||||||
|
interfaceDefaultCallsPhase then
|
||||||
|
|
||||||
singleAbstractMethodPhase then
|
singleAbstractMethodPhase then
|
||||||
addContinuationPhase then
|
addContinuationPhase then
|
||||||
@@ -145,13 +154,13 @@ private val jvmFilePhases =
|
|||||||
enumClassPhase then
|
enumClassPhase then
|
||||||
objectClassPhase then
|
objectClassPhase then
|
||||||
makeInitializersPhase(JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true) then
|
makeInitializersPhase(JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true) then
|
||||||
syntheticAccessorPhase then
|
|
||||||
collectionStubMethodLowering then
|
collectionStubMethodLowering then
|
||||||
bridgePhase then
|
bridgePhase then
|
||||||
jvmOverloadsAnnotationPhase then
|
jvmOverloadsAnnotationPhase then
|
||||||
jvmDefaultConstructorPhase then
|
jvmDefaultConstructorPhase then
|
||||||
jvmStaticAnnotationPhase then
|
jvmStaticAnnotationPhase then
|
||||||
staticDefaultFunctionPhase then
|
staticDefaultFunctionPhase then
|
||||||
|
syntheticAccessorPhase then
|
||||||
|
|
||||||
toArrayPhase then
|
toArrayPhase then
|
||||||
flattenStringConcatenationPhase then
|
flattenStringConcatenationPhase then
|
||||||
|
|||||||
+28
@@ -211,6 +211,34 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val interfaceDefaultCallsPhase = makeIrFilePhase(
|
||||||
|
lowering = ::InterfaceDefaultCallsLowering,
|
||||||
|
name = "InterfaceDefaultCalls",
|
||||||
|
description = "Redirect interface calls with default arguments to DefaultImpls"
|
||||||
|
)
|
||||||
|
|
||||||
|
private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
|
||||||
|
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.transformChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
val callee = expression.symbol.owner
|
||||||
|
|
||||||
|
if (callee.parent.safeAs<IrClass>()?.isInterface != true ||
|
||||||
|
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER
|
||||||
|
) {
|
||||||
|
return super.visitCall(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
val redirectTarget = context.declarationFactory.getDefaultImplsFunction(callee as IrSimpleFunction)
|
||||||
|
val newCall = irCall(expression, redirectTarget, receiversAsArguments = true)
|
||||||
|
|
||||||
|
return super.visitCall(newCall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod() =
|
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod() =
|
||||||
resolveFakeOverride()?.let { origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB } == true ||
|
resolveFakeOverride()?.let { origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB } == true ||
|
||||||
|
|||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.underlyingType
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
|
||||||
|
class JvmDefaultParameterInjector(context: JvmBackendContext) :
|
||||||
|
DefaultParameterInjector(context, skipInline = false, skipExternalMethods = false) {
|
||||||
|
|
||||||
|
override val context: JvmBackendContext get() = super.context as JvmBackendContext
|
||||||
|
|
||||||
|
override fun nullConst(expression: IrElement, type: IrType): IrExpression {
|
||||||
|
if (type !is IrSimpleType ||
|
||||||
|
type.hasQuestionMark ||
|
||||||
|
type.classOrNull?.owner?.isInline != true
|
||||||
|
) {
|
||||||
|
return super.nullConst(expression, type)
|
||||||
|
}
|
||||||
|
val underlyingType = type.classOrNull!!.owner.underlyingType()
|
||||||
|
return IrCallImpl(
|
||||||
|
expression.startOffset, expression.endOffset,
|
||||||
|
type,
|
||||||
|
context.ir.symbols.unsafeCoerceIntrinsicSymbol, context.ir.symbols.unsafeCoerceIntrinsicSymbol.descriptor,
|
||||||
|
typeArgumentsCount = 2,
|
||||||
|
valueArgumentsCount = 1
|
||||||
|
).apply {
|
||||||
|
putTypeArgument(0, underlyingType) // from
|
||||||
|
putTypeArgument(1, type) // to
|
||||||
|
putValueArgument(0, super.nullConst(expression, underlyingType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+56
-15
@@ -16,30 +16,45 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
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.ClassLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.copyBodyToStatic
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers
|
import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers
|
||||||
|
import org.jetbrains.kotlin.backend.common.phaser.SameTypeNamedPhaseWrapper
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
|
import org.jetbrains.kotlin.backend.common.phaser.then
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
|
||||||
internal val staticDefaultFunctionPhase = makeIrFilePhase(
|
private val functionDefinitionLoweringPhase = makeIrFilePhase(
|
||||||
::StaticDefaultFunctionLowering,
|
::StaticDefaultFunctionLowering,
|
||||||
name = "StaticDefaultFunction",
|
name = "StaticDefaultFunctionDefinition",
|
||||||
description = "Generate static functions for default parameters"
|
description = "Generate static functions for default parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
private class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), ClassLoweringPass {
|
private val callLoweringPhase = makeIrFilePhase(
|
||||||
constructor(@Suppress("UNUSED_PARAMETER") context: BackendContext) : this()
|
::StaticDefaultCallLowering,
|
||||||
|
name = "StaticDefaultCall",
|
||||||
|
description = "Generate calls of static functions for default parameters"
|
||||||
|
)
|
||||||
|
|
||||||
val updatedFunctions = hashMapOf<IrFunctionSymbol, IrFunction>()
|
internal val staticDefaultFunctionPhase = SameTypeNamedPhaseWrapper(
|
||||||
|
name = "StaticDefaultFunction",
|
||||||
|
description = "Make function adapters for default arguments static",
|
||||||
|
lower = functionDefinitionLoweringPhase then callLoweringPhase,
|
||||||
|
prerequisite = setOf(jvmStaticAnnotationPhase),
|
||||||
|
nlevels = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
private class StaticDefaultFunctionLowering(val context: JvmBackendContext) : IrElementTransformerVoid(),
|
||||||
|
ClassLoweringPass {
|
||||||
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
irClass.accept(this, null)
|
irClass.accept(this, null)
|
||||||
@@ -47,9 +62,9 @@ private class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), Clas
|
|||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
return if (declaration.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null) {
|
return if (declaration.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null) {
|
||||||
return createStaticFunctionWithReceivers(declaration.parent, declaration.name, declaration).also {
|
context.getStaticFunctionWithReceivers(declaration).also {
|
||||||
updatedFunctions[declaration.symbol] = it
|
copyBodyToStatic(declaration, it)
|
||||||
super.visitFunction(declaration)
|
super.visitFunction(it)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
super.visitFunction(declaration)
|
super.visitFunction(declaration)
|
||||||
@@ -58,9 +73,9 @@ private class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), Clas
|
|||||||
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
return super.visitReturn(
|
return super.visitReturn(
|
||||||
if (updatedFunctions.containsKey(expression.returnTargetSymbol)) {
|
if (context.staticDefaultStubs.containsKey(expression.returnTargetSymbol)) {
|
||||||
with(expression) {
|
with(expression) {
|
||||||
val irFunction = updatedFunctions[expression.returnTargetSymbol]!!
|
val irFunction = context.staticDefaultStubs[expression.returnTargetSymbol]!!
|
||||||
IrReturnImpl(startOffset, endOffset, expression.type, irFunction.symbol, expression.value)
|
IrReturnImpl(startOffset, endOffset, expression.type, irFunction.symbol, expression.value)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -69,3 +84,29 @@ private class StaticDefaultFunctionLowering() : IrElementTransformerVoid(), Clas
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StaticDefaultCallLowering(
|
||||||
|
val context: JvmBackendContext
|
||||||
|
) : IrElementTransformerVoid(), FileLoweringPass {
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.accept(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
val callee = expression.symbol.owner
|
||||||
|
if (callee.origin !== IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || callee.dispatchReceiverParameter == null) {
|
||||||
|
return super.visitCall(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
val newCallee = context.getStaticFunctionWithReceivers(callee)
|
||||||
|
val newCall = irCall(expression, newCallee, receiversAsArguments = true)
|
||||||
|
|
||||||
|
return super.visitCall(newCall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JvmBackendContext.getStaticFunctionWithReceivers(function: IrFunction) =
|
||||||
|
staticDefaultStubs.getOrPut(function.symbol) {
|
||||||
|
createStaticFunctionWithReceivers(function.parent, function.name, function, copyBody = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ internal val syntheticAccessorPhase = makeIrFilePhase(
|
|||||||
::SyntheticAccessorLowering,
|
::SyntheticAccessorLowering,
|
||||||
name = "SyntheticAccessor",
|
name = "SyntheticAccessor",
|
||||||
description = "Introduce synthetic accessors",
|
description = "Introduce synthetic accessors",
|
||||||
prerequisite = setOf(objectClassPhase)
|
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
||||||
|
|||||||
Reference in New Issue
Block a user