Skip to content

Commit 08ac802

Browse files
committed
Coro: Add a function attribute for resume from call async functlets
This change adds a function attribute `async_ret` for any funclet generated from a async function marked with `async_entry` that models a return from an async function. We recognize these continuations by a `__swift_async_resume_project_context` projection function argument to the suspend function. rdar://134460666
1 parent 4857f75 commit 08ac802

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,21 @@ void CoroCloner::create() {
10351035
// Transfer the original function's attributes.
10361036
auto FnAttrs = OrigF.getAttributes().getFnAttrs();
10371037
NewAttrs = NewAttrs.addFnAttributes(Context, AttrBuilder(Context, FnAttrs));
1038+
1039+
// Mark async funclets that "pop the frame" if the async function is marked
1040+
// with the `async_entry` function attribute. Remove the `async_entry`
1041+
// attribute from clones.
1042+
bool HasAsyncEntryAttribute = OrigF.hasFnAttribute("async_entry");
1043+
auto ProjectionFunctionName =
1044+
ActiveAsyncSuspend->getAsyncContextProjectionFunction()->getName();
1045+
bool IsAsyncFramePop =
1046+
ProjectionFunctionName.equals("__swift_async_resume_project_context");
1047+
if (HasAsyncEntryAttribute) {
1048+
NewAttrs = NewAttrs.removeFnAttribute(Context, "async_entry");
1049+
if (IsAsyncFramePop) {
1050+
NewAttrs = NewAttrs.addFnAttribute(Context, "async_ret");
1051+
}
1052+
}
10381053
break;
10391054
}
10401055
case coro::ABI::Retcon:

llvm/test/Transforms/Coroutines/coro-async.ll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ entry:
5858
}
5959

6060

61-
define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 {
61+
define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine "async_entry" !dbg !1 {
6262
entry:
6363
%tmp = alloca { i64, i64 }, align 8
6464
%vector = alloca <4 x double>, align 16
@@ -145,6 +145,7 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
145145

146146
; CHECK-LABEL: define internal swifttailcc void @my_async_functionTQ0_(ptr nocapture readonly swiftasync %0, ptr %1, ptr nocapture readnone %2)
147147
; CHECK-O0-LABEL: define internal swifttailcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2)
148+
; CHECK-SAME: #[[ATTRS:[0-9]+]]
148149
; CHECK-SAME: !dbg ![[SP2:[0-9]+]] {
149150
; CHECK: entryresume.0:
150151
; CHECK: [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0
@@ -514,6 +515,8 @@ declare ptr @hide(ptr)
514515
!llvm.dbg.cu = !{!2}
515516
!llvm.module.flags = !{!0}
516517

518+
; CHECK: #[[ATTRS]] = {{.*}}async_ret
519+
517520
!0 = !{i32 2, !"Debug Info Version", i32 3}
518521
; CHECK: ![[SP1]] = distinct !DISubprogram(name: "my_async_function",
519522
; CHECK-SAME: linkageName: "my_async_function",

0 commit comments

Comments
 (0)