From 671ce74e97ed4f69aad0aa71afcc46408f337d12 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 11 Oct 2021 04:13:05 -0700 Subject: [PATCH] [IRGen] Put 'ret void' instead of unreachable for non swiftasync cc If target doesn't support musttail (e.g. WebAssembly), the function passed to coro.end.async can return control back to the caller. So the frontend should emit 'ret void' instead of unreachable after the coro.end.async intrinsic call to allow such situation. --- lib/IRGen/GenCall.cpp | 10 +++++++++- test/IRGen/async/non_musttail_target.sil | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/IRGen/async/non_musttail_target.sil 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 +}