diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt index 80f74c5cce5..c89573f6fc2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt @@ -28,6 +28,8 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin +import org.jetbrains.kotlin.ir.expressions.IrTypeOperator +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -72,6 +74,38 @@ inline fun IrGeneratorWithScope.irBlock(expression: IrExpression, origin: IrStat inline fun IrGeneratorWithScope.irBlockBody(irElement: IrElement, body: IrBlockBodyBuilder.() -> Unit) = this.irBlockBody(irElement.startOffset, irElement.endOffset, body) + +fun IrBuilderWithScope.irUnit() = + IrGetObjectValueImpl(startOffset, endOffset, context.builtIns.unitType, context.builtIns.unit) + +fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) = + IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null) + +fun IrBuilderWithScope.irGet(descriptor: PropertyDescriptor) = + IrGetterCallImpl(startOffset, endOffset, descriptor.getter!!, null) + +fun IrBuilderWithScope.irSet(receiver: IrExpression, descriptor: PropertyDescriptor, arg: IrExpression) = + IrSetterCallImpl(startOffset, endOffset, descriptor.setter!!, null, receiver, null, arg) + +fun IrBuilderWithScope.irNot(arg: IrExpression) = + primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNot, IrStatementOrigin.EXCL, arg) + +fun IrBuilderWithScope.irThrow(arg: IrExpression) = + IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg) + +fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) = + IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, typeOperand, arg) + +fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) = + IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.unitType, + IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg) + +fun IrBuilderWithScope.irGetField(receiver: IrExpression, descriptor: PropertyDescriptor) = + IrGetFieldImpl(startOffset, endOffset, descriptor, receiver) + +fun IrBuilderWithScope.irSetField(receiver: IrExpression, descriptor: PropertyDescriptor, value: IrExpression) = + IrSetFieldImpl(startOffset, endOffset, descriptor, receiver, value) + open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() { private var currentBuilder: IrBuilderWithScope? = null diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt index cb6d7a47554..2ea4c52cedd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SuspendFunctionsLowering.kt @@ -21,7 +21,10 @@ import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters import org.jetbrains.kotlin.backend.common.descriptors.isSuspend import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.* +import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass +import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions +import org.jetbrains.kotlin.backend.konan.descriptors.isSuspendFunctionInvoke +import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.util.atMostOne import org.jetbrains.kotlin.descriptors.* @@ -1131,7 +1134,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai continue } first = false - if (!transformedChild.isPure() && hasSuspendCallInTail[index]) { + if (transformedChild.isPure() || !hasSuspendCallInTail[index]) + newChildren[index] = transformedChild + else { // Save to temporary in order to save execution order. val tmp = IrTemporaryVariableDescriptorImpl( containingDeclaration = irFunction.descriptor, @@ -1140,27 +1145,24 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai tempStatements += irVar(tmp, transformedChild) newChildren[index] = irGet(tmp) } - else newChildren[index] = transformedChild } var calledSaveState = false if (expression.isSuspendCall) { val lastChild = newChildren.last() if (lastChild != null) { - // Save state at late as possible. + // Save state as late as possible. calledSaveState = true newChildren[numberOfChildren - 1] = - if (lastChild.isPure()) - irBlock(lastChild) { + irBlock(lastChild) { + if (lastChild.isPure()) { +irCall(saveStateDescriptor) +lastChild - } - else { - val tmp = IrTemporaryVariableDescriptorImpl( - containingDeclaration = irFunction.descriptor, - name = "tmp${tempIndex++}".synthesizedName, - outType = lastChild.type) - irBlock(lastChild) { + } else { + val tmp = IrTemporaryVariableDescriptorImpl( + containingDeclaration = irFunction.descriptor, + name = "tmp${tempIndex++}".synthesizedName, + outType = lastChild.type) +irVar(tmp, lastChild) +irCall(saveStateDescriptor) +irGet(tmp) @@ -1233,9 +1235,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai private val IrExpression.isSuspendCall: Boolean get() = this is IrCall && this.descriptor.isSuspend - private object STATEMENT_ORIGIN_COROUTINE_IMPL: IrStatementOriginImpl("COROUTINE_IMPL") + private object STATEMENT_ORIGIN_COROUTINE_IMPL : + IrStatementOriginImpl("COROUTINE_IMPL") - private fun IrElement.isSpecialBlock() = this is IrBlock && this.origin == STATEMENT_ORIGIN_COROUTINE_IMPL + private fun IrElement.isSpecialBlock() + = this is IrBlock && this.origin == STATEMENT_ORIGIN_COROUTINE_IMPL private fun IrElement.hasSuspendCalls(): Boolean { var hasSuspendCalls = false @@ -1257,7 +1261,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai return when (this) { is IrConst<*> -> true is IrCall -> false // TODO: skip builtin operators. - is IrTypeOperatorCall -> this.argument.isPure() + is IrTypeOperatorCall -> this.argument.isPure() && this.operator != IrTypeOperator.CAST is IrGetValue -> !this.descriptor.let { it is VariableDescriptor && it.isVar } else -> false } @@ -1315,34 +1319,4 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai scopeStack.peek()!!.add(declaration.descriptor) } } - - fun IrBuilderWithScope.irUnit() = - IrGetObjectValueImpl(startOffset, endOffset, context.builtIns.unitType, context.builtIns.unit) - - fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) = - IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null) - - fun IrBuilderWithScope.irGet(descriptor: PropertyDescriptor) = - IrGetterCallImpl(startOffset, endOffset, descriptor.getter!!, null) - - fun IrBuilderWithScope.irSet(receiver: IrExpression, descriptor: PropertyDescriptor, arg: IrExpression) = - IrSetterCallImpl(startOffset, endOffset, descriptor.setter!!, null, receiver, null, arg) - - fun IrBuilderWithScope.irNot(arg: IrExpression) = - primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNot, IrStatementOrigin.EXCL, arg) - - fun IrBuilderWithScope.irThrow(arg: IrExpression) = - IrThrowImpl(startOffset, endOffset, arg.type, arg) - - fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) = - IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, typeOperand, arg) - - fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) = - IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.unitType, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg) - - fun IrBuilderWithScope.irGetField(receiver: IrExpression, descriptor: PropertyDescriptor) = - IrGetFieldImpl(startOffset, endOffset, descriptor, receiver) - - fun IrBuilderWithScope.irSetField(receiver: IrExpression, descriptor: PropertyDescriptor, value: IrExpression) = - IrSetFieldImpl(startOffset, endOffset, descriptor, receiver, value) } \ No newline at end of file