IR: unify 3 copies of function body remapping
Also,
1. remove some redundant copies;
2. fix remapping of non-local returns in lambdas if the body is moved
after LocalDeclarationsLowering (the lambda is no longer inside the
body, but must still be visited)
This commit is contained in:
+54
-18
@@ -6,13 +6,14 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.ir
|
package org.jetbrains.kotlin.backend.common.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||||
import org.jetbrains.kotlin.ir.util.isVararg
|
import org.jetbrains.kotlin.ir.util.isVararg
|
||||||
import org.jetbrains.kotlin.ir.util.statements
|
import org.jetbrains.kotlin.ir.util.statements
|
||||||
|
|
||||||
@@ -36,21 +37,56 @@ fun IrExpression.asSimpleLambda(): IrSimpleFunction? {
|
|||||||
return function
|
return function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createParameterMapping(source: IrFunction, target: IrFunction): Map<IrValueParameter, IrValueParameter> {
|
||||||
|
val sourceParameters = listOfNotNull(source.dispatchReceiverParameter, source.extensionReceiverParameter) + source.valueParameters
|
||||||
|
val targetParameters = listOfNotNull(target.dispatchReceiverParameter, target.extensionReceiverParameter) + target.valueParameters
|
||||||
|
assert(sourceParameters.size == targetParameters.size)
|
||||||
|
return sourceParameters.zip(targetParameters).toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrFunction.copyBodyTo(target: IrFunction): IrBody? =
|
||||||
|
copyBodyTo(target, createParameterMapping(this, target))
|
||||||
|
|
||||||
|
fun IrFunction.copyBodyTo(target: IrFunction, arguments: Map<IrValueParameter, IrValueDeclaration>): IrBody? =
|
||||||
|
body?.deepCopyWithSymbols(target)?.move(this, target, target.symbol, arguments)
|
||||||
|
|
||||||
|
fun IrFunction.moveBodyTo(target: IrFunction): IrBody? =
|
||||||
|
moveBodyTo(target, createParameterMapping(this, target))
|
||||||
|
|
||||||
|
fun IrFunction.moveBodyTo(target: IrFunction, arguments: Map<IrValueParameter, IrValueDeclaration>): IrBody? =
|
||||||
|
body?.move(this, target, target.symbol, arguments)
|
||||||
|
|
||||||
|
private fun IrBody.move(
|
||||||
|
source: IrFunction,
|
||||||
|
target: IrDeclarationParent,
|
||||||
|
targetSymbol: IrReturnTargetSymbol,
|
||||||
|
arguments: Map<IrValueParameter, IrValueDeclaration>
|
||||||
|
): IrBody = transform(object : VariableRemapper(arguments) {
|
||||||
|
override fun visitReturn(expression: IrReturn): IrExpression = super.visitReturn(
|
||||||
|
if (expression.returnTargetSymbol == source.symbol)
|
||||||
|
IrReturnImpl(expression.startOffset, expression.endOffset, expression.type, targetSymbol, expression.value)
|
||||||
|
else
|
||||||
|
expression
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun visitBlock(expression: IrBlock): IrExpression {
|
||||||
|
// Might be an inline lambda argument; if the function has already been moved out, visit it explicitly.
|
||||||
|
if (expression.origin == IrStatementOrigin.LAMBDA || expression.origin == IrStatementOrigin.ANONYMOUS_FUNCTION)
|
||||||
|
if (expression.statements[0] !is IrFunction && expression.statements[1] is IrFunctionReference)
|
||||||
|
(expression.statements[1] as IrFunctionReference).symbol.owner.transformChildrenVoid()
|
||||||
|
return super.visitBlock(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
|
||||||
|
if (declaration.parent == source)
|
||||||
|
declaration.parent = target
|
||||||
|
return super.visitDeclaration(declaration)
|
||||||
|
}
|
||||||
|
}, null)
|
||||||
|
|
||||||
// TODO use a generic inliner (e.g. JS/Native's FunctionInlining.Inliner)
|
// TODO use a generic inliner (e.g. JS/Native's FunctionInlining.Inliner)
|
||||||
// Inline simple function calls without type parameters, default parameters, or varargs.
|
// Inline simple function calls without type parameters, default parameters, or varargs.
|
||||||
fun IrFunction.inline(arguments: List<IrValueDeclaration> = listOf()): IrReturnableBlock {
|
fun IrFunction.inline(target: IrDeclarationParent, arguments: List<IrValueDeclaration> = listOf()): IrReturnableBlock =
|
||||||
require(body != null)
|
IrReturnableBlockImpl(startOffset, endOffset, returnType, IrReturnableBlockSymbolImpl(descriptor), null, symbol).apply {
|
||||||
val argumentMap = valueParameters.zip(arguments).toMap()
|
statements += body!!.move(this@inline, target, symbol, valueParameters.zip(arguments).toMap()).statements
|
||||||
val blockSymbol = IrReturnableBlockSymbolImpl(descriptor)
|
|
||||||
val block = IrReturnableBlockImpl(startOffset, endOffset, returnType, blockSymbol, null, symbol)
|
|
||||||
val remapper = object : VariableRemapper(argumentMap) {
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression = super.visitReturn(
|
|
||||||
if (expression.returnTargetSymbol == symbol)
|
|
||||||
IrReturnImpl(expression.startOffset, expression.endOffset, expression.type, blockSymbol, expression.value)
|
|
||||||
else
|
|
||||||
expression
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
body!!.statements.mapTo(block.statements) { it.transform(remapper, null) }
|
|
||||||
return block
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -598,46 +598,5 @@ fun createStaticFunctionWithReceivers(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyBodyToStatic(oldFunction: IrFunction, staticFunction: IrFunction) {
|
|
||||||
val mapping: Map<IrValueParameter, IrValueParameter> =
|
|
||||||
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
|
|
||||||
.zip(staticFunction.valueParameters).toMap()
|
|
||||||
copyBodyWithParametersMapping(staticFunction, oldFunction, mapping)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyBodyWithParametersMapping(
|
|
||||||
newFunction: IrFunction,
|
|
||||||
oldFunction: IrFunction,
|
|
||||||
mapping: Map<IrValueParameter, IrValueParameter>
|
|
||||||
) {
|
|
||||||
newFunction.body = oldFunction.body?.deepCopyWithSymbols(oldFunction)
|
|
||||||
?.transform(
|
|
||||||
object : IrElementTransformerVoid() {
|
|
||||||
// Remap return targets to the static method so they do not appear to be
|
|
||||||
// non-local returns.
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this);
|
|
||||||
return if (expression.returnTargetSymbol == oldFunction.symbol) {
|
|
||||||
IrReturnImpl(
|
|
||||||
expression.startOffset,
|
|
||||||
expression.endOffset,
|
|
||||||
expression.type,
|
|
||||||
newFunction.symbol,
|
|
||||||
expression.value
|
|
||||||
)
|
|
||||||
} else expression
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remap argument values.
|
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression =
|
|
||||||
mapping[expression.symbol.owner]?.let {
|
|
||||||
IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol, expression.origin)
|
|
||||||
} ?: expression
|
|
||||||
|
|
||||||
}, null
|
|
||||||
)
|
|
||||||
?.patchDeclarationParents(newFunction)
|
|
||||||
}
|
|
||||||
|
|
||||||
val IrSymbol.isSuspend: Boolean
|
val IrSymbol.isSuspend: Boolean
|
||||||
get() = this is IrSimpleFunctionSymbol && owner.isSuspend
|
get() = this is IrSimpleFunctionSymbol && owner.isSuspend
|
||||||
|
|||||||
+1
-6
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.ir.types.getClass
|
|||||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
import org.jetbrains.kotlin.ir.util.functions
|
import org.jetbrains.kotlin.ir.util.functions
|
||||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
@@ -84,7 +83,7 @@ class ArrayConstructorLowering(val context: CommonBackendContext) : IrElementTra
|
|||||||
}
|
}
|
||||||
body = irBlock {
|
body = irBlock {
|
||||||
val tempIndex = irTemporary(irGet(index))
|
val tempIndex = irTemporary(irGet(index))
|
||||||
val value = lambda?.inline(listOf(tempIndex)) ?: irCallOp(
|
val value = lambda?.inline(parent, listOf(tempIndex)) ?: irCallOp(
|
||||||
invoke.symbol,
|
invoke.symbol,
|
||||||
invoke.returnType,
|
invoke.returnType,
|
||||||
irGet(invokableVar!!),
|
irGet(invokableVar!!),
|
||||||
@@ -100,10 +99,6 @@ class ArrayConstructorLowering(val context: CommonBackendContext) : IrElementTra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
+irGet(result)
|
+irGet(result)
|
||||||
}.also {
|
|
||||||
// Some parents of local declarations are not updated during ad-hoc inlining
|
|
||||||
// TODO: Remove when generic inliner is used
|
|
||||||
it.patchDeclarationParents(scope.getLocalDeclarationParent())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-9
@@ -221,13 +221,6 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.copyBodyFrom(oldFunction: IrFunction) {
|
|
||||||
val mapping: Map<IrValueParameter, IrValueParameter> =
|
|
||||||
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
|
|
||||||
.zip(listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).toMap()
|
|
||||||
copyBodyWithParametersMapping(this, oldFunction, mapping)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrDeclarationContainer.addFunctionOverride(
|
private fun IrDeclarationContainer.addFunctionOverride(
|
||||||
function: IrSimpleFunction,
|
function: IrSimpleFunction,
|
||||||
modality: Modality = Modality.FINAL
|
modality: Modality = Modality.FINAL
|
||||||
@@ -517,7 +510,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
origin = JvmLoweredDeclarationOrigin.SUSPEND_IMPL_STATIC_FUNCTION,
|
origin = JvmLoweredDeclarationOrigin.SUSPEND_IMPL_STATIC_FUNCTION,
|
||||||
copyMetadata = false
|
copyMetadata = false
|
||||||
)
|
)
|
||||||
copyBodyToStatic(irFunction, static)
|
static.body = irFunction.moveBodyTo(static)
|
||||||
// Rewrite the body of the original suspend method to forward to the new static method.
|
// Rewrite the body of the original suspend method to forward to the new static method.
|
||||||
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
||||||
+irReturn(irCall(static).also {
|
+irReturn(irCall(static).also {
|
||||||
@@ -568,7 +561,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this)
|
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this)
|
||||||
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this)
|
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this)
|
||||||
function.valueParameters.mapTo(valueParameters) { it.copyTo(this) }
|
function.valueParameters.mapTo(valueParameters) { it.copyTo(this) }
|
||||||
copyBodyFrom(function)
|
body = function.copyBodyTo(this)
|
||||||
copyAttributes(function)
|
copyAttributes(function)
|
||||||
}
|
}
|
||||||
registerNewFunction(function.parentAsClass, newFunction)
|
registerNewFunction(function.parentAsClass, newFunction)
|
||||||
|
|||||||
+1
-5
@@ -67,10 +67,6 @@ private class AssertionLowering(private val context: JvmBackendContext) :
|
|||||||
// to be false, meaning that assertions are checked.
|
// to be false, meaning that assertions are checked.
|
||||||
info.assertionsDisabledField?.let {
|
info.assertionsDisabledField?.let {
|
||||||
declaration.declarations.add(0, it)
|
declaration.declarations.add(0, it)
|
||||||
|
|
||||||
// Some parents of local declarations are not updated during ad-hoc inlining
|
|
||||||
// TODO: Remove when generic inliner is used
|
|
||||||
declaration.patchDeclarationParents(declaration.parent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return declaration
|
return declaration
|
||||||
@@ -112,7 +108,7 @@ private class AssertionLowering(private val context: JvmBackendContext) :
|
|||||||
putValueArgument(
|
putValueArgument(
|
||||||
0,
|
0,
|
||||||
when {
|
when {
|
||||||
lambda != null -> lambda.inline()
|
lambda != null -> lambda.inline(parent)
|
||||||
lambdaArgument != null -> {
|
lambdaArgument != null -> {
|
||||||
val invoke =
|
val invoke =
|
||||||
lambdaArgument.type.getClass()!!.functions.single { it.name == OperatorNameConventions.INVOKE }
|
lambdaArgument.type.getClass()!!.functions.single { it.name == OperatorNameConventions.INVOKE }
|
||||||
|
|||||||
+2
-31
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||||
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.moveBodyTo
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
@@ -20,7 +21,6 @@ import org.jetbrains.kotlin.backend.jvm.ir.irArray
|
|||||||
import org.jetbrains.kotlin.backend.jvm.ir.isLambda
|
import org.jetbrains.kotlin.backend.jvm.ir.isLambda
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
|
||||||
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.*
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||||
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
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.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
@@ -243,35 +242,7 @@ internal class CallableReferenceLowering(private val context: JvmBackendContext)
|
|||||||
param to param.copyTo(this, index = index)
|
param to param.copyTo(this, index = index)
|
||||||
}
|
}
|
||||||
valueParameters += valueParameterMap.values
|
valueParameters += valueParameterMap.values
|
||||||
|
body = callee.moveBodyTo(this, valueParameterMap)
|
||||||
val calleeBody = callee.body as IrBlockBody
|
|
||||||
body = context.createIrBuilder(symbol).irBlockBody(calleeBody.startOffset, calleeBody.endOffset) {
|
|
||||||
calleeBody.statements.forEach { statement ->
|
|
||||||
+statement.transform(object : IrElementTransformerVoid() {
|
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
|
||||||
val replacement = valueParameterMap[expression.symbol.owner]
|
|
||||||
?: return super.visitGetValue(expression)
|
|
||||||
|
|
||||||
at(expression.startOffset, expression.endOffset)
|
|
||||||
return irGet(replacement)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression =
|
|
||||||
if (expression.returnTargetSymbol != callee.symbol) {
|
|
||||||
super.visitReturn(expression)
|
|
||||||
} else {
|
|
||||||
at(expression.startOffset, expression.endOffset)
|
|
||||||
irReturn(expression.value.transform(this, null))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
|
|
||||||
if (declaration.parent == callee)
|
|
||||||
declaration.parent = this@createLambdaInvokeMethod
|
|
||||||
return super.visitDeclaration(declaration)
|
|
||||||
}
|
|
||||||
}, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrSimpleFunction.createFunctionReferenceInvokeMethod(receiver: IrValueDeclaration?) {
|
private fun IrSimpleFunction.createFunctionReferenceInvokeMethod(receiver: IrValueDeclaration?) {
|
||||||
|
|||||||
+6
-9
@@ -6,8 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.ir.copyBodyToStatic
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.moveBodyTo
|
||||||
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
@@ -122,7 +122,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
|||||||
|| (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.hasJvmDefault())
|
|| (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.hasJvmDefault())
|
||||||
|| function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS -> {
|
|| function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS -> {
|
||||||
val defaultImpl = createDefaultImpl(function)
|
val defaultImpl = createDefaultImpl(function)
|
||||||
function.copyImplementationTo(defaultImpl)
|
defaultImpl.body = function.moveBodyTo(defaultImpl)
|
||||||
removedFunctions[function.symbol] = defaultImpl.symbol
|
removedFunctions[function.symbol] = defaultImpl.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
|||||||
*/
|
*/
|
||||||
!function.hasJvmDefault() -> {
|
!function.hasJvmDefault() -> {
|
||||||
val defaultImpl = createDefaultImpl(function)
|
val defaultImpl = createDefaultImpl(function)
|
||||||
function.copyImplementationTo(defaultImpl)
|
defaultImpl.body = function.moveBodyTo(defaultImpl)
|
||||||
function.body = null
|
function.body = null
|
||||||
//TODO reset modality to abstract
|
//TODO reset modality to abstract
|
||||||
}
|
}
|
||||||
@@ -176,20 +176,17 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
|||||||
if (annotationsMethods.none()) return
|
if (annotationsMethods.none()) return
|
||||||
|
|
||||||
for (function in annotationsMethods) {
|
for (function in annotationsMethods) {
|
||||||
removedFunctions[function.symbol] = createDefaultImpl(function).symbol
|
val defaultImpl = createDefaultImpl(function)
|
||||||
|
defaultImpl.body = function.moveBodyTo(defaultImpl)
|
||||||
|
removedFunctions[function.symbol] = defaultImpl.symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDefaultImpl(function: IrSimpleFunction): IrSimpleFunction =
|
private fun createDefaultImpl(function: IrSimpleFunction): IrSimpleFunction =
|
||||||
context.declarationFactory.getDefaultImplsFunction(function).also { newFunction ->
|
context.declarationFactory.getDefaultImplsFunction(function).also { newFunction ->
|
||||||
newFunction.body = function.body?.patchDeclarationParents(newFunction)
|
|
||||||
newFunction.parentAsClass.declarations.add(newFunction)
|
newFunction.parentAsClass.declarations.add(newFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrSimpleFunction.copyImplementationTo(target: IrSimpleFunction) {
|
|
||||||
copyBodyToStatic(this, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bridge from static to static method - simply fill the arguments to the parameters.
|
// Bridge from static to static method - simply fill the arguments to the parameters.
|
||||||
// By nature of the generation of both source and target of bridge, they line up.
|
// By nature of the generation of both source and target of bridge, they line up.
|
||||||
private fun IrFunction.bridgeToStatic(callTarget: IrFunction) {
|
private fun IrFunction.bridgeToStatic(callTarget: IrFunction) {
|
||||||
|
|||||||
+8
-12
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
|||||||
|
|
||||||
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.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.ir.moveBodyTo
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.SameTypeNamedPhaseWrapper
|
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.common.phaser.then
|
||||||
@@ -60,16 +60,14 @@ private class StaticDefaultFunctionLowering(val context: JvmBackendContext) : Ir
|
|||||||
irClass.accept(this, null)
|
irClass.accept(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
override fun visitFunction(declaration: IrFunction): IrStatement = super.visitFunction(
|
||||||
return if (declaration.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null) {
|
if (declaration.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null)
|
||||||
context.getStaticFunctionWithReceivers(declaration).also {
|
context.getStaticFunctionWithReceivers(declaration).also {
|
||||||
copyBodyToStatic(declaration, it)
|
it.body = declaration.moveBodyTo(it)
|
||||||
super.visitFunction(it)
|
|
||||||
}
|
}
|
||||||
} else {
|
else
|
||||||
super.visitFunction(declaration)
|
declaration
|
||||||
}
|
)
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||||
return super.visitReturn(
|
return super.visitReturn(
|
||||||
@@ -94,9 +92,7 @@ private class StaticDefaultCallLowering(
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
val callee = expression.symbol.owner
|
val callee = expression.symbol.owner
|
||||||
if (callee.origin !== IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
if (callee.origin !== IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || expression.dispatchReceiver == null) {
|
||||||
expression.dispatchReceiver == null
|
|
||||||
) {
|
|
||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun myRun(f: () -> Nothing): Nothing = f()
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
val ok: String
|
||||||
|
get() { myRun { return "OK" } }
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : I
|
||||||
|
|
||||||
|
fun box(): String = C().ok
|
||||||
+5
@@ -2119,6 +2119,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fromInterfaceDefaultGetter.kt")
|
||||||
|
public void testFromInterfaceDefaultGetter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("justReturnInLambda.kt")
|
@TestMetadata("justReturnInLambda.kt")
|
||||||
public void testJustReturnInLambda() throws Exception {
|
public void testJustReturnInLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
||||||
|
|||||||
Generated
+5
@@ -2119,6 +2119,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fromInterfaceDefaultGetter.kt")
|
||||||
|
public void testFromInterfaceDefaultGetter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("justReturnInLambda.kt")
|
@TestMetadata("justReturnInLambda.kt")
|
||||||
public void testJustReturnInLambda() throws Exception {
|
public void testJustReturnInLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
||||||
|
|||||||
+5
@@ -2119,6 +2119,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
|||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fromInterfaceDefaultGetter.kt")
|
||||||
|
public void testFromInterfaceDefaultGetter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("justReturnInLambda.kt")
|
@TestMetadata("justReturnInLambda.kt")
|
||||||
public void testJustReturnInLambda() throws Exception {
|
public void testJustReturnInLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
||||||
|
|||||||
Generated
+5
@@ -2119,6 +2119,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
|||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fromInterfaceDefaultGetter.kt")
|
||||||
|
public void testFromInterfaceDefaultGetter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("justReturnInLambda.kt")
|
@TestMetadata("justReturnInLambda.kt")
|
||||||
public void testJustReturnInLambda() throws Exception {
|
public void testJustReturnInLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
||||||
|
|||||||
Generated
+5
@@ -34,6 +34,11 @@ public class IrNonLocalReturnsTestGenerated extends AbstractIrNonLocalReturnsTes
|
|||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fromInterfaceDefaultGetter.kt")
|
||||||
|
public void testFromInterfaceDefaultGetter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("justReturnInLambda.kt")
|
@TestMetadata("justReturnInLambda.kt")
|
||||||
public void testJustReturnInLambda() throws Exception {
|
public void testJustReturnInLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
||||||
|
|||||||
+5
@@ -34,6 +34,11 @@ public class NonLocalReturnsTestGenerated extends AbstractNonLocalReturnsTest {
|
|||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/explicitLocalReturn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fromInterfaceDefaultGetter.kt")
|
||||||
|
public void testFromInterfaceDefaultGetter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/fromInterfaceDefaultGetter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("justReturnInLambda.kt")
|
@TestMetadata("justReturnInLambda.kt")
|
||||||
public void testJustReturnInLambda() throws Exception {
|
public void testJustReturnInLambda() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
runTest("compiler/testData/codegen/boxInline/nonLocalReturns/justReturnInLambda.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user