diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 5d8269477b096..e516f0a5966c0 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -4929,7 +4929,15 @@ void irgen::emitAsyncReturn( arguments.push_back(arg); Builder.CreateIntrinsicCall(llvm::Intrinsic::coro_end_async, arguments); - Builder.CreateUnreachable(); + + if (IGF.IGM.AsyncTailCallKind == llvm::CallInst::TCK_MustTail) { + Builder.CreateUnreachable(); + } else { + // If target doesn't support musttail (e.g. WebAssembly), the function + // passed to coro.end.async can return control back to the caller. + // So use ret void instead of unreachable to allow it. + Builder.CreateRetVoid(); + } } void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout, diff --git a/test/IRGen/async/non_musttail_target.sil b/test/IRGen/async/non_musttail_target.sil new file mode 100644 index 0000000000000..5907c237f51b6 --- /dev/null +++ b/test/IRGen/async/non_musttail_target.sil @@ -0,0 +1,17 @@ +// Ensure that IRGen don't emit unreachable after coro.end.async for targets that don't support musttail call. +// RUN: %swift -disable-legacy-type-info -parse-stdlib -target wasm32-unknown-wasi %s -disable-llvm-optzns -disable-swift-specific-llvm-optzns -disable-objc-interop -module-name main -emit-ir -o - | %FileCheck %s +// REQUIRES: concurrency +// REQUIRES: CODEGENERATOR=WebAssembly + +sil_stage canonical + +import Builtin + +sil @test_simple : $@async () -> () { +bb0: + %0 = tuple () + return %0 : $() +// CHECK: call i1 (i8*, i1, ...) @llvm.coro.end.async +// CHECK-NOT: unreachable +// CHECK: ret void +}