[JVM_IR] Copy offsets from the original function to invokeSuspend.

Otherwise, implicit returns in void returning suspend functions
will not have the line number of the end brace.

Fixes KT-41962 and KT-40464.
This commit is contained in:
Mads Ager
2020-10-14 14:46:55 +02:00
committed by Alexander Udalov
parent 800bfe2cdb
commit ad88c60fd8
8 changed files with 29 additions and 10 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.builders.declarations
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
@@ -168,9 +169,13 @@ fun IrClass.addFunction(
isStatic: Boolean = false, isStatic: Boolean = false,
isSuspend: Boolean = false, isSuspend: Boolean = false,
isFakeOverride: Boolean = false, isFakeOverride: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET
): IrSimpleFunction = ): IrSimpleFunction =
addFunction { addFunction {
this.startOffset = startOffset
this.endOffset = endOffset
this.name = Name.identifier(name) this.name = Name.identifier(name)
this.returnType = returnType this.returnType = returnType
this.modality = modality this.modality = modality
@@ -158,7 +158,7 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
val backendContext = context val backendContext = context
val invokeSuspend = context.ir.symbols.continuationImplClass.owner.functions val invokeSuspend = context.ir.symbols.continuationImplClass.owner.functions
.single { it.name == Name.identifier(INVOKE_SUSPEND_METHOD_NAME) } .single { it.name == Name.identifier(INVOKE_SUSPEND_METHOD_NAME) }
addFunctionOverride(invokeSuspend) { function -> addFunctionOverride(invokeSuspend, irFunction.startOffset, irFunction.endOffset) { function ->
+irSetField(irGet(function.dispatchReceiverParameter!!), resultField, irGet(function.valueParameters[0])) +irSetField(irGet(function.dispatchReceiverParameter!!), resultField, irGet(function.valueParameters[0]))
// There can be three kinds of suspend function call: // There can be three kinds of suspend function call:
// 1) direct call from another suspend function/lambda // 1) direct call from another suspend function/lambda
@@ -73,17 +73,21 @@ private fun IrFunction.capturesCrossinline(): Boolean {
} }
internal abstract class SuspendLoweringUtils(protected val context: JvmBackendContext) { internal abstract class SuspendLoweringUtils(protected val context: JvmBackendContext) {
protected fun IrClass.addFunctionOverride(function: IrSimpleFunction): IrSimpleFunction = protected fun IrClass.addFunctionOverride(
addFunction(function.name.asString(), function.returnType).apply { function: IrSimpleFunction, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET
): IrSimpleFunction =
addFunction(function.name.asString(), function.returnType, startOffset = startOffset, endOffset = endOffset).apply {
overriddenSymbols = listOf(function.symbol) overriddenSymbols = listOf(function.symbol)
valueParameters = function.valueParameters.map { it.copyTo(this) } valueParameters = function.valueParameters.map { it.copyTo(this) }
} }
protected fun IrClass.addFunctionOverride( protected fun IrClass.addFunctionOverride(
function: IrSimpleFunction, function: IrSimpleFunction,
startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET,
makeBody: IrBlockBodyBuilder.(IrFunction) -> Unit makeBody: IrBlockBodyBuilder.(IrFunction) -> Unit
): IrSimpleFunction = ): IrSimpleFunction =
addFunctionOverride(function).apply { addFunctionOverride(function, startOffset, endOffset).apply {
body = context.createIrBuilder(symbol).irBlockBody { makeBody(this@apply) } body = context.createIrBuilder(symbol).irBlockBody { makeBody(this@apply) }
} }
@@ -196,7 +200,7 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin
it.owner.name.asString() == INVOKE_SUSPEND_METHOD_NAME && it.owner.valueParameters.size == 1 && it.owner.name.asString() == INVOKE_SUSPEND_METHOD_NAME && it.owner.valueParameters.size == 1 &&
it.owner.valueParameters[0].type.isKotlinResult() it.owner.valueParameters[0].type.isKotlinResult()
}.owner }.owner
return addFunctionOverride(superMethod).apply { return addFunctionOverride(superMethod, irFunction.startOffset, irFunction.endOffset).apply {
body = irFunction.moveBodyTo(this, mapOf())?.transform(object : IrElementTransformerVoid() { body = irFunction.moveBodyTo(this, mapOf())?.transform(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
val parameter = (expression.symbol.owner as? IrValueParameter)?.takeIf { it.parent == irFunction } val parameter = (expression.symbol.owner as? IrValueParameter)?.takeIf { it.parent == irFunction }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
LineBreakpoint created at sequenceNested.kt:6 LineBreakpoint created at sequenceNested.kt:6
Run Java Run Java
Connected to the target VM Connected to the target VM
@@ -0,0 +1,14 @@
LineBreakpoint created at sequenceNested2.kt:8
Run Java
Connected to the target VM
sequenceNested2.kt:8
sequenceNested2.kt:9
sequenceNested2.kt:10
sequenceNested2.kt:11
sequenceNested2.kt:23
sequenceNested2.kt:23
sequenceNested2.kt:23
sequenceNested2.kt:24
Disconnected from the target VM
Process finished with exit code 0
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
LineBreakpoint created at sequenceNested2.kt:8 LineBreakpoint created at sequenceNested2.kt:8
Run Java Run Java
Connected to the target VM Connected to the target VM
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
LineBreakpoint created at sequenceSimple.kt:6 LineBreakpoint created at sequenceSimple.kt:6
Run Java Run Java
Connected to the target VM Connected to the target VM
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
LineBreakpoint created at soSuspendableCallInEndOfFun.kt:29 LineBreakpoint created at soSuspendableCallInEndOfFun.kt:29
Run Java Run Java
Connected to the target VM Connected to the target VM