diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt index fbc75c3238b..ffd58ad3005 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CallableReferenceLowering.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt index 6988f48c476..c7e533927b1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MainMethodGenerationLowering.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2020 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. */ @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ir.allParameters +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.jvm.JvmBackendContext @@ -18,15 +20,18 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.builders.declarations.addFunction -import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.copyAttributes +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.isFileClass +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance @@ -130,19 +135,74 @@ private class MainMethodGenerationLowering(private val context: JvmBackendContex body = context.createIrBuilder(symbol).irBlockBody { makeBody(args) } } - private fun IrBuilderWithScope.irRunSuspend(target: IrSimpleFunction, args: IrValueParameter?) = - irCall(this@MainMethodGenerationLowering.context.ir.symbols.runSuspendFunction).apply { - val reference = IrFunctionReferenceImpl( - UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - this@MainMethodGenerationLowering.context.ir.symbols.suspendFunctionN(0).typeWith(context.irBuiltIns.anyNType), - target.symbol, - typeArgumentsCount = 0, - reflectionTarget = null - ) - if (args != null) { - reference.putValueArgument(0, irGet(args)) + private fun IrBuilderWithScope.irRunSuspend(target: IrSimpleFunction, args: IrValueParameter?): IrExpression { + val backendContext = this@MainMethodGenerationLowering.context + return irBlock { + val wrapperConstructor = buildClass { + name = Name.special("") + visibility = JavaVisibilities.PACKAGE_VISIBILITY + modality = Modality.FINAL + origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL + }.let { wrapper -> + +wrapper + + wrapper.createImplicitParameterDeclarationWithWrappedDescriptor() + + val lambdaSuperClass = backendContext.ir.symbols.lambdaClass + val functionClass = backendContext.ir.symbols.getJvmSuspendFunctionClass(0) + + wrapper.superTypes += lambdaSuperClass.defaultType + wrapper.superTypes += functionClass.typeWith(backendContext.irBuiltIns.anyNType) + wrapper.parent = target.parent + + val stringArrayType = backendContext.irBuiltIns.arrayClass.typeWith(backendContext.irBuiltIns.stringType) + val argsField = args?.let { wrapper.addField("args", stringArrayType) } + + wrapper.addFunction("invoke", backendContext.irBuiltIns.anyNType, isSuspend = true).also { invoke -> + val invokeToOverride = functionClass.functions.single() + + invoke.overriddenSymbols += invokeToOverride + invoke.body = backendContext.createIrBuilder(invoke.symbol).irBlockBody { + +irReturn(irCall(target.symbol).also { call -> + if (args != null) { + call.putValueArgument(0, irGetField(irGet(invoke.dispatchReceiverParameter!!), argsField!!)) + } + }) + } + } + + wrapper.addConstructor { + isPrimary = true + visibility = JavaVisibilities.PACKAGE_VISIBILITY + }.also { constructor -> + val superClassConstructor = lambdaSuperClass.owner.constructors.single() + val param = args?.let { constructor.addValueParameter("args", stringArrayType) } + + constructor.body = backendContext.createIrBuilder(constructor.symbol).irBlockBody { + +irDelegatingConstructorCall(superClassConstructor).also { + it.putValueArgument(0, irInt(1)) + } + if (args != null) { + +irSetField(irGet(wrapper.thisReceiver!!), argsField!!, irGet(param!!)) + } + } + } + } + + +irCall(backendContext.ir.symbols.runSuspendFunction).apply { + putValueArgument( + 0, IrConstructorCallImpl.fromSymbolOwner( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + wrapperConstructor.returnType, + wrapperConstructor.symbol + ).also { + if (args != null) { + it.putValueArgument(0, irGet(args)) + } + } + ) } - putValueArgument(0, reference) } + } } \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/main/multifileSuspend.kt b/compiler/testData/codegen/bytecodeListing/main/multifileSuspend.kt index 459fbdc1bc8..2c5c1a1bd42 100644 --- a/compiler/testData/codegen/bytecodeListing/main/multifileSuspend.kt +++ b/compiler/testData/codegen/bytecodeListing/main/multifileSuspend.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME @file:JvmMultifileClass @file:JvmName("Foo") diff --git a/compiler/testData/codegen/bytecodeListing/main/multifileSuspend_ir.txt b/compiler/testData/codegen/bytecodeListing/main/multifileSuspend_ir.txt new file mode 100644 index 00000000000..852932f1dad --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/multifileSuspend_ir.txt @@ -0,0 +1,22 @@ +@kotlin.Metadata +public final class Hello/Foo { + public final static method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void + public final static @org.jetbrains.annotations.Nullable method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[], @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} + +@kotlin.Metadata +synthetic final class Hello/Foo__MultifileSuspendKt$main$2 { + private field args: java.lang.String[] + inner class Hello/Foo__MultifileSuspendKt$main$2 + method (@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void + public final @org.jetbrains.annotations.Nullable method invoke(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object + public synthetic bridge @org.jetbrains.annotations.Nullable method invoke(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +@kotlin.jvm.JvmName +synthetic final class Hello/Foo__MultifileSuspendKt { + inner class Hello/Foo__MultifileSuspendKt$main$2 + public synthetic final static method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void + public final static @org.jetbrains.annotations.Nullable method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[], @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} diff --git a/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt index ed4dd2d4709..1eb139e269f 100644 --- a/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt +++ b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME fun main() {} diff --git a/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_ir.txt b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_ir.txt new file mode 100644 index 00000000000..cce0f0c777a --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/parameterlessMain_ir.txt @@ -0,0 +1,5 @@ +@kotlin.Metadata +public final class ParameterlessMainKt { + public final static method main(): void + public synthetic final static method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void +} diff --git a/compiler/testData/codegen/bytecodeListing/main/suspendMain.kt b/compiler/testData/codegen/bytecodeListing/main/suspendMain.kt index 5686bd25b48..6bce5e92de0 100644 --- a/compiler/testData/codegen/bytecodeListing/main/suspendMain.kt +++ b/compiler/testData/codegen/bytecodeListing/main/suspendMain.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME suspend fun main(args: Array) {} diff --git a/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt b/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt index eb85884b63c..2858c25d1ef 100644 --- a/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt +++ b/compiler/testData/codegen/bytecodeListing/main/suspendMain_before.kt @@ -1,4 +1,5 @@ // !LANGUAGE: -ExtendedMainConvention -ReleaseCoroutines +// Does not run on JVM_IR since it uses experimental coroutines // IGNORE_BACKEND: JVM_IR // WITH_RUNTIME diff --git a/compiler/testData/codegen/bytecodeListing/main/suspendMain_ir.txt b/compiler/testData/codegen/bytecodeListing/main/suspendMain_ir.txt new file mode 100644 index 00000000000..2b4338410b0 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/main/suspendMain_ir.txt @@ -0,0 +1,15 @@ +@kotlin.Metadata +synthetic final class SuspendMainKt$main$2 { + private field args: java.lang.String[] + inner class SuspendMainKt$main$2 + method (@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void + public final @org.jetbrains.annotations.Nullable method invoke(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object + public synthetic bridge @org.jetbrains.annotations.Nullable method invoke(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class SuspendMainKt { + inner class SuspendMainKt$main$2 + public synthetic final static method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[]): void + public final static @org.jetbrains.annotations.Nullable method main(@org.jetbrains.annotations.NotNull p0: java.lang.String[], @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +}