Coroutines: support of Unit functions

This commit is contained in:
Igor Chevdar
2017-04-27 11:38:44 +03:00
parent 6aa3493de2
commit 4f22b4803a
2 changed files with 14 additions and 8 deletions
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.backend.konan.KonanPhase
import org.jetbrains.kotlin.backend.konan.PhaseManager
import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.IrInlineFunctionBody
import org.jetbrains.kotlin.backend.konan.ir.IrSuspendableExpression
import org.jetbrains.kotlin.backend.konan.ir.IrSuspensionPoint
import org.jetbrains.kotlin.backend.konan.ir.ir2string
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
@@ -493,7 +490,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
if (declaration == null || target == declaration.descriptor) {
if (target.returnType!!.isUnit()) {
if (target.returnsUnit()) {
assert (value == null)
codegen.ret(null)
} else {
@@ -1457,7 +1454,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val evaluated = evaluateExpression(value)
val target = expression.returnTarget
val ret = if (target.returnType!!.isUnit()) {
val ret = if (target.returnsUnit()) {
null
} else {
evaluated
@@ -1498,7 +1495,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
// It is local return from current function.
codegen.br(getExit()) // Generate branch on exit block.
if (!KotlinBuiltIns.isUnit(inlineBody.type)) { // If function returns more then "unit"
if (!target.returnsUnit()) { // If function returns more then "unit"
codegen.assignPhis(getResult() to value!!) // Assign return value to result PHI node.
}
}
@@ -1752,6 +1749,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
}
}
private fun CallableDescriptor.returnsUnit() = returnType == context.builtIns.unitType && !isSuspend
/**
* Evaluates all arguments of [expression] that are explicitly represented in the IR.
* Returns results in the same order as LLVM function expects, assuming that all explicit arguments
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
internal class SuspendFunctionsLowering(val context: Context): DeclarationContainerLoweringPass {
@@ -827,6 +828,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
statements.forEach { +it }
})
if (irFunction.descriptor.returnType!!.isUnit())
+irReturn(irUnit()) // Insert explicit return for Unit functions.
}
}
}
@@ -1039,7 +1042,11 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
+irGet(dataArgument)
})
tempStatements.add(irVar(currentSuspendResult, suspensionPoint))
return irWrap(irCast(irGet(currentSuspendResult), suspendCall.type, suspendCall.type), tempStatements)
val expressionResult = when {
suspendCall.type.isUnit() -> IrCompositeImpl(startOffset, endOffset, suspendCall.type)
else -> irCast(irGet(currentSuspendResult), suspendCall.type, suspendCall.type)
}
return irWrap(expressionResult, tempStatements)
}
}