[K/N] Use suspend function desugaring lowerings.
This commit is contained in:
committed by
Space Team
parent
8886e1b8b4
commit
817dba8564
@@ -20,6 +20,7 @@ interface Mapping {
|
||||
val capturedConstructors: Delegate<IrConstructor, IrConstructor>
|
||||
val reflectedNameAccessor: Delegate<IrClass, IrSimpleFunction>
|
||||
val suspendFunctionsToFunctionWithContinuations: Delegate<IrSimpleFunction, IrSimpleFunction>
|
||||
val functionWithContinuationsToSuspendFunctions: Delegate<IrSimpleFunction, IrSimpleFunction>
|
||||
|
||||
abstract class Delegate<K : IrDeclaration, V> {
|
||||
abstract operator fun get(key: K): V?
|
||||
@@ -77,6 +78,7 @@ open class DefaultMapping(delegateFactory: DelegateFactory = DefaultDelegateFact
|
||||
override val capturedConstructors: Mapping.Delegate<IrConstructor, IrConstructor> = delegateFactory.newDeclarationToDeclarationMapping()
|
||||
override val reflectedNameAccessor: Mapping.Delegate<IrClass, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
|
||||
override val suspendFunctionsToFunctionWithContinuations: Mapping.Delegate<IrSimpleFunction, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
|
||||
override val functionWithContinuationsToSuspendFunctions: Mapping.Delegate<IrSimpleFunction, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
|
||||
}
|
||||
|
||||
fun <V : Any> KMutableProperty0<V?>.getOrPut(fn: () -> V) = this.get() ?: fn().also {
|
||||
|
||||
+5
-107
@@ -6,8 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -19,7 +17,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -33,9 +30,6 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
protected abstract val stateMachineMethodName: Name
|
||||
protected abstract fun getCoroutineBaseClass(function: IrFunction): IrClassSymbol
|
||||
protected abstract fun nameForCoroutineClass(function: IrFunction): Name
|
||||
protected abstract fun IrBuilderWithScope.launchSuspendFunctionWithGivenContinuation(
|
||||
symbol: IrSimpleFunctionSymbol, superQualifierSymbol: IrClassSymbol?, dispatchReceiver: IrExpression,
|
||||
arguments: List<IrExpression>, continuation: IrExpression) : IrExpression
|
||||
|
||||
protected abstract fun buildStateMachine(
|
||||
stateMachineFunction: IrFunction,
|
||||
@@ -57,106 +51,6 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
markSuspendLambdas(irFile)
|
||||
buildCoroutines(irFile)
|
||||
transformCallableReferencesToSuspendLambdas(irFile)
|
||||
addMissingSupertypesToSuspendFunctionImplementingClasses(irFile)
|
||||
}
|
||||
|
||||
private fun addMissingSupertypesToSuspendFunctionImplementingClasses(irFile: IrFile) {
|
||||
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
// Don't need to iterate through children. All local classes are already moved to the top level by this moment.
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
addMissingSupertypes(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
|
||||
private fun addMissingSupertypes(clazz: IrClass) {
|
||||
val suspendFunctionTypes = getAllSubstitutedSupertypes(clazz).filter {
|
||||
// SuspendFunction class is some hack in old Kotlin/Native compiler versions.
|
||||
// It's not used now, but is considered as SuspendFunction-like class in isSuspendFunction util,
|
||||
// if found in old klib. We need just to ignore it.
|
||||
it.isSuspendFunction() && it.classOrNull?.owner?.name?.toString() != "SuspendFunction"
|
||||
}.toSet()
|
||||
|
||||
for (suspendFunctionType in suspendFunctionTypes) {
|
||||
val suspendFunctionClassSymbol = suspendFunctionType.classOrNull ?: continue
|
||||
val suspendFunction = suspendFunctionClassSymbol.owner.simpleFunctions().single {
|
||||
it.name == OperatorNameConventions.INVOKE
|
||||
}
|
||||
|
||||
val invokeFunction = clazz.simpleFunctions().single {
|
||||
it.name == OperatorNameConventions.INVOKE && it.overrides(suspendFunction)
|
||||
}
|
||||
|
||||
if (invokeFunction.modality == Modality.ABSTRACT) {
|
||||
continue
|
||||
}
|
||||
|
||||
val suspendFunctionArity = suspendFunction.valueParameters.size
|
||||
val functionClassSymbol = symbols.functionN(suspendFunctionArity + 1)
|
||||
val functionSymbol = functionClassSymbol.owner.simpleFunctions().single {
|
||||
it.name == OperatorNameConventions.INVOKE
|
||||
}.symbol
|
||||
|
||||
val functionClassTypeArguments = suspendFunctionType.arguments.mapIndexed { index, argument ->
|
||||
val type = (argument as IrTypeProjection).type
|
||||
if (index == suspendFunctionArity) continuationClassSymbol.typeWith(type) else type
|
||||
} + context.irBuiltIns.anyNType
|
||||
|
||||
val functionType = functionClassSymbol.typeWith(functionClassTypeArguments)
|
||||
|
||||
clazz.superTypes += functionType
|
||||
|
||||
context.irFactory.buildFun {
|
||||
startOffset = SYNTHETIC_OFFSET
|
||||
endOffset = SYNTHETIC_OFFSET
|
||||
origin = DECLARATION_ORIGIN_COROUTINE_IMPL
|
||||
name = OperatorNameConventions.INVOKE
|
||||
visibility = DescriptorVisibilities.PROTECTED
|
||||
returnType = context.irBuiltIns.anyNType
|
||||
}.apply {
|
||||
parent = clazz
|
||||
clazz.declarations += this
|
||||
|
||||
typeParameters = invokeFunction.typeParameters.map { parameter ->
|
||||
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
|
||||
.apply { superTypes += parameter.superTypes }
|
||||
}
|
||||
|
||||
valueParameters = invokeFunction.valueParameters
|
||||
.mapIndexed { index, parameter ->
|
||||
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
|
||||
}
|
||||
valueParameters += buildValueParameter(this) {
|
||||
index = valueParameters.size
|
||||
type = context.irBuiltIns.anyNType
|
||||
name = "completion".synthesizedName
|
||||
}
|
||||
|
||||
this.createDispatchReceiverParameter()
|
||||
|
||||
overriddenSymbols += functionSymbol
|
||||
|
||||
val thisReceiver = dispatchReceiverParameter!!
|
||||
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
+irReturn(
|
||||
launchSuspendFunctionWithGivenContinuation(
|
||||
invokeFunction.symbol,
|
||||
superQualifierSymbol = invokeFunction.parentAsClass.symbol, // Call non-virtually.
|
||||
irGet(thisReceiver),
|
||||
valueParameters.dropLast(1).map { irGet(it) },
|
||||
irGet(valueParameters.last())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun buildCoroutines(irFile: IrFile) {
|
||||
@@ -433,7 +327,9 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
)
|
||||
|
||||
val suspendInvokeFunction =
|
||||
suspendFunctionClass!!.simpleFunctions().single { it.name == OperatorNameConventions.INVOKE }
|
||||
suspendFunctionClass!!.simpleFunctions().single { it.name == OperatorNameConventions.INVOKE }.let {
|
||||
context.mapping.functionWithContinuationsToSuspendFunctions[it] ?: it
|
||||
}
|
||||
|
||||
buildInvokeMethod(
|
||||
functionInvokeFunction = suspendInvokeFunction,
|
||||
@@ -722,3 +618,5 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
private val CREATE_IDENTIFIER = Name.identifier("create")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -226,7 +226,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
||||
body = context.createIrBuilder(symbol).irBlockBody {
|
||||
+irReturn(
|
||||
irCall(
|
||||
wrappedFunctionClass.functions.single { it.name == OperatorNameConventions.INVOKE }.symbol,
|
||||
getSuspendFunctionWithoutContinuation(wrappedFunctionClass.functions.single { it.name == OperatorNameConventions.INVOKE }).symbol,
|
||||
originalSuperMethod.returnType
|
||||
).apply {
|
||||
dispatchReceiver = irGetField(irGet(dispatchReceiverParameter!!), field)
|
||||
|
||||
+5
-3
@@ -88,12 +88,14 @@ private fun transformSuspendFunction(context: CommonBackendContext, function: Ir
|
||||
|
||||
fun IrSimpleFunction.getOrCreateFunctionWithContinuationStub(context: CommonBackendContext): IrSimpleFunction {
|
||||
return context.mapping.suspendFunctionsToFunctionWithContinuations.getOrPut(this) {
|
||||
createSuspendFunctionStub(context)
|
||||
createSuspendFunctionStub(context).also {
|
||||
context.mapping.functionWithContinuationsToSuspendFunctions[it] = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.createSuspendFunctionStub(context: CommonBackendContext): IrSimpleFunction {
|
||||
require(this.isSuspend)
|
||||
require(this.isSuspend) { "$fqNameWhenAvailable should be a suspend function to create version with contunation" }
|
||||
return factory.buildFun {
|
||||
updateFrom(this@createSuspendFunctionStub)
|
||||
isSuspend = false
|
||||
@@ -103,9 +105,9 @@ private fun IrSimpleFunction.createSuspendFunctionStub(context: CommonBackendCon
|
||||
}.also { function ->
|
||||
function.parent = parent
|
||||
|
||||
function.annotations += annotations
|
||||
function.metadata = metadata
|
||||
|
||||
function.copyAnnotationsFrom(this)
|
||||
function.copyAttributes(this)
|
||||
function.copyTypeParametersFrom(this)
|
||||
val substitutionMap = makeTypeParameterSubstitutionMap(this, function)
|
||||
|
||||
Reference in New Issue
Block a user