Skip to content

Commit c1776ee

Browse files
authored
Merge pull request #40451 from compnerd/ret-void
[5.5] Cherry-pick a change from main to handle missing mandatory tail call optimizations
2 parents ef1fbfd + 9fbf41c commit c1776ee

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4949,7 +4949,15 @@ void irgen::emitAsyncReturn(
49494949
arguments.push_back(arg);
49504950

49514951
Builder.CreateIntrinsicCall(llvm::Intrinsic::coro_end_async, arguments);
4952-
Builder.CreateUnreachable();
4952+
4953+
if (IGF.IGM.AsyncTailCallKind == llvm::CallInst::TCK_MustTail) {
4954+
Builder.CreateUnreachable();
4955+
} else {
4956+
// If target doesn't support musttail (e.g. WebAssembly), the function
4957+
// passed to coro.end.async can return control back to the caller.
4958+
// So use ret void instead of unreachable to allow it.
4959+
Builder.CreateRetVoid();
4960+
}
49534961
}
49544962

49554963
void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,

test/IRGen/async/hop_to_executor.sil

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
// RUN: %target-swift-frontend -enable-experimental-concurrency -primary-file %s -module-name=test -disable-llvm-optzns -disable-swift-specific-llvm-optzns -emit-ir -sil-verify-all | %IRGenFileCheck %s
1+
// RUN: %target-swift-frontend -enable-experimental-concurrency -primary-file %s -module-name=test -disable-llvm-optzns -disable-swift-specific-llvm-optzns -emit-ir -sil-verify-all | %IRGenFileCheck %s -check-prefix CHECK-%target-abi
22

33
// REQUIRES: concurrency
44

5+
// WASI does not support the mandatory tail call, and needs to take the same
6+
// path as CHECK-WIN, but will currently go down CHECK-SYSV, failing the test.
7+
// XFAIL: OS=wasi
8+
59
sil_stage canonical
610

711
import Builtin
@@ -10,13 +14,14 @@ import _Concurrency
1014

1115
// CHECK-LABEL: define{{.*}} void @test_simple(
1216
// CHECK-SAME: %swift.context* swiftasync %0, [[INT]] %1, [[INT]] %2)
13-
// CHECK: [[CTX:%[0-9]+]] = bitcast %swift.context* %0
14-
// CHECK: [[RESUME:%[0-9]+]] = call i8* @llvm.coro.async.resume()
17+
// CHECK-DAG: [[CTX:%[0-9]+]] = bitcast %swift.context* %0
18+
// CHECK-DAG: [[RESUME:%[0-9]+]] = call i8* @llvm.coro.async.resume()
1519
// CHECK-x86_64: call {{.*}} @llvm.coro.suspend.async{{.*}}(i32 0, i8* [[RESUME]], i8* bitcast (i8* (i8*)* @__swift_async_resume_get_context to i8*), i8* bitcast (void (i8*, [[INT]], [[INT]], %swift.context*)* @__swift_suspend_point to i8*), i8* [[RESUME]], [[INT]] %1, [[INT]] %2, %swift.context* {{%[0-9]+}})
1620
// CHECK-arm64e: call {{.*}} @llvm.coro.suspend.async{{.*}}(i32 0, i8* [[RESUME]], i8* bitcast (i8* (i8*)* @__swift_async_resume_get_context to i8*), i8* bitcast (void (i8*, [[INT]], [[INT]], %swift.context*)* @__swift_suspend_point to i8*), i8* [[RESUME]], [[INT]] %1, [[INT]] %2, %swift.context* {{%[0-9]+}})
1721
// CHECK: [[RET_CONTINUATION:%.*]] = bitcast void (%swift.context*)* {{.*}} to i8*
1822
// CHECK: call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* {{.*}}, i1 false, void (i8*, %swift.context*)* @[[TAIL_CALL_FUNC:.*]], i8* [[RET_CONTINUATION]]
19-
// CHECK: unreachable
23+
// CHECK-WIN: ret void
24+
// CHECK-SYSV: unreachable
2025

2126
sil @test_simple : $@async (@guaranteed Optional<Builtin.Executor>) -> () {
2227
bb0(%0 : $Optional<Builtin.Executor>):
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Ensure that IRGen don't emit unreachable after coro.end.async for targets that don't support musttail call.
2+
// RUN: %target-swift-frontend -disable-legacy-type-info -parse-stdlib %s -disable-llvm-optzns -disable-swift-specific-llvm-optzns -disable-objc-interop -module-name main -emit-ir -o - | %FileCheck %s
3+
4+
// REQUIRES: concurrency
5+
// REQUIRES: OS=wasi || OS=windows-msvc
6+
7+
sil_stage canonical
8+
9+
import Builtin
10+
11+
sil @test_simple : $@async () -> () {
12+
bb0:
13+
%0 = tuple ()
14+
return %0 : $()
15+
// CHECK: call i1 (i8*, i1, ...) @llvm.coro.end.async
16+
// CHECK-NOT: unreachable
17+
// CHECK: ret void
18+
}

0 commit comments

Comments
 (0)