JVM_IR: Return COROUTINE_SUSPENDED from suspend main wrapper

Before, if the code inside suspend main suspended, the wrapper would
just ignore it and return Unit. This was a signal for runSuspend to exit
main loop and return said Unit.
Instead of poping whatever suspend main returns, just return it.
This commit is contained in:
Ilmir Usmanov
2020-02-20 18:08:43 +01:00
parent 5b62c9e54d
commit 8c4eef9844
@@ -29,7 +29,9 @@ import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.isFileClass import org.jetbrains.kotlin.ir.util.isFileClass
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -81,9 +83,9 @@ private class MainMethodGenerationLowering(private val context: JvmBackendContex
if (mainMethod.isSuspend) { if (mainMethod.isSuspend) {
generateMainMethod(irClass) { args -> generateMainMethod(irClass) { args ->
body = buildRunSuspendWrapper { body = buildRunSuspendWrapper {
+irCall(mainMethod).apply { +IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.nothingType, it, irCall(mainMethod).apply {
putValueArgument(0, irGet(args)) putValueArgument(0, irGet(args))
} })
} }
} }
} }
@@ -94,7 +96,7 @@ private class MainMethodGenerationLowering(private val context: JvmBackendContex
generateMainMethod(irClass) { generateMainMethod(irClass) {
body = if (parameterlessMainMethod.isSuspend) { body = if (parameterlessMainMethod.isSuspend) {
buildRunSuspendWrapper { buildRunSuspendWrapper {
+irCall(parameterlessMainMethod) +IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.nothingType, it, irCall(parameterlessMainMethod))
} }
} else { } else {
context.createIrBuilder(symbol).irBlockBody { context.createIrBuilder(symbol).irBlockBody {
@@ -147,19 +149,19 @@ private class MainMethodGenerationLowering(private val context: JvmBackendContex
} }
} }
private fun IrFunctionImpl.buildRunSuspendWrapper(buildMainInvocation: IrBlockBodyBuilder.() -> Unit) = private fun IrFunctionImpl.buildRunSuspendWrapper(buildMainInvocation: IrBlockBodyBuilder.(IrSimpleFunctionSymbol) -> Unit) =
context.createJvmIrBuilder(symbol).irBlockBody { context.createJvmIrBuilder(symbol).irBlockBody {
val lambda = irBlock(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrStatementOrigin.LAMBDA) { val lambda = irBlock(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrStatementOrigin.LAMBDA) {
val function = buildFun { val function = buildFun {
origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
name = Name.identifier("wrapper_for_suspend_main") name = Name.identifier("wrapper_for_suspend_main")
visibility = Visibilities.LOCAL visibility = Visibilities.LOCAL
returnType = context.irBuiltIns.unitType returnType = context.irBuiltIns.anyNType
}.apply { }.apply {
addValueParameter("k", context.irBuiltIns.anyNType) addValueParameter("k", context.irBuiltIns.anyNType)
parent = this parent = this
body = irBlockBody { body = irBlockBody {
buildMainInvocation() buildMainInvocation(symbol)
} }
} }
+function +function
@@ -168,7 +170,7 @@ private class MainMethodGenerationLowering(private val context: JvmBackendContex
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.irBuiltIns.function1.typeWith( context.irBuiltIns.function1.typeWith(
context.irBuiltIns.anyNType, context.irBuiltIns.anyNType,
context.irBuiltIns.unitType context.irBuiltIns.anyNType
), ),
function.symbol, function.symbol,
typeArgumentsCount = 0, typeArgumentsCount = 0,