Skip to content

Commit 13f109c

Browse files
authored
Reland "Cherry-pick 51d5d7b from LLVM mainline" (#8199)
* Update coroutine intrinsics documentation and few remaining tests to opaque pointers (llvm#65698) * Extend `retcon.once` coroutines lowering to optionally produce a normal result (llvm#66333) One of the main user of these kind of coroutines is swift. There yield-once (`retcon.once`) coroutines are used to temporary "expose" pointers to internal fields of various objects creating borrow scopes. However, in some cases it might be useful also to allow these coroutines to produce a normal result, but there is no convenient way to represent this (as compared to switched-resume kind of coroutines where C++ `co_return` is transformed to a member / callback call on promise object). The extension is simple: we allow continuation function to have a non-void result and accept optional extra arguments via a special `llvm.coro.end.result` intrinsic that would essentially forward them as normal results.
1 parent 87789f0 commit 13f109c

File tree

128 files changed

+917
-495
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+917
-495
lines changed

clang/lib/CodeGen/CGCoroutine.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,11 @@ struct CallCoroEnd final : public EHScopeStack::Cleanup {
402402
llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
403403
// See if we have a funclet bundle to associate coro.end with. (WinEH)
404404
auto Bundles = getBundlesForCoroEnd(CGF);
405-
auto *CoroEnd = CGF.Builder.CreateCall(
406-
CoroEndFn, {NullPtr, CGF.Builder.getTrue()}, Bundles);
405+
auto *CoroEnd =
406+
CGF.Builder.CreateCall(CoroEndFn,
407+
{NullPtr, CGF.Builder.getTrue(),
408+
llvm::ConstantTokenNone::get(CoroEndFn->getContext())},
409+
Bundles);
407410
if (Bundles.empty()) {
408411
// Otherwise, (landingpad model), create a conditional branch that leads
409412
// either to a cleanup block or a block with EH resume instruction.
@@ -754,7 +757,9 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
754757
// Emit coro.end before getReturnStmt (and parameter destructors), since
755758
// resume and destroy parts of the coroutine should not include them.
756759
llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
757-
Builder.CreateCall(CoroEnd, {NullPtr, Builder.getFalse()});
760+
Builder.CreateCall(CoroEnd,
761+
{NullPtr, Builder.getFalse(),
762+
llvm::ConstantTokenNone::get(CoroEnd->getContext())});
758763

759764
if (Stmt *Ret = S.getReturnStmt()) {
760765
// Since we already emitted the return value above, so we shouldn't
@@ -823,7 +828,11 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
823828
}
824829
for (const Expr *Arg : E->arguments())
825830
Args.push_back(EmitScalarExpr(Arg));
826-
831+
// @llvm.coro.end takes a token parameter. Add token 'none' as the last
832+
// argument.
833+
if (IID == llvm::Intrinsic::coro_end)
834+
Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));
835+
827836
llvm::Function *F = CGM.getIntrinsic(IID);
828837
llvm::CallInst *Call = Builder.CreateCall(F, Args);
829838

clang/test/CodeGenCoroutines/coro-builtins.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void f(int n) {
3737
// CHECK-NEXT: call ptr @llvm.coro.free(token %[[COROID]], ptr %[[FRAME]])
3838
__builtin_coro_free(__builtin_coro_frame());
3939

40-
// CHECK-NEXT: call i1 @llvm.coro.end(ptr %[[FRAME]], i1 false)
40+
// CHECK-NEXT: call i1 @llvm.coro.end(ptr %[[FRAME]], i1 false, token none)
4141
__builtin_coro_end(__builtin_coro_frame(), 0);
4242

4343
// CHECK-NEXT: call i8 @llvm.coro.suspend(token none, i1 true)

clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ coro_t f() {
6060

6161
// CHECK: [[COROENDBB]]:
6262
// CHECK-NEXT: %[[CLPAD:.+]] = cleanuppad within none
63-
// CHECK-NEXT: call i1 @llvm.coro.end(ptr null, i1 true) [ "funclet"(token %[[CLPAD]]) ]
63+
// CHECK-NEXT: call i1 @llvm.coro.end(ptr null, i1 true, token none) [ "funclet"(token %[[CLPAD]]) ]
6464
// CHECK-NEXT: cleanupret from %[[CLPAD]] unwind label
6565

6666
// CHECK-LPAD: @_Z1fv(
@@ -76,7 +76,7 @@ coro_t f() {
7676
// CHECK-LPAD: to label %{{.+}} unwind label %[[UNWINDBB:.+]]
7777

7878
// CHECK-LPAD: [[UNWINDBB]]:
79-
// CHECK-LPAD: %[[I1RESUME:.+]] = call i1 @llvm.coro.end(ptr null, i1 true)
79+
// CHECK-LPAD: %[[I1RESUME:.+]] = call i1 @llvm.coro.end(ptr null, i1 true, token none)
8080
// CHECK-LPAD: br i1 %[[I1RESUME]], label %[[EHRESUME:.+]], label
8181
// CHECK-LPAD: [[EHRESUME]]:
8282
// CHECK-LPAD-NEXT: %[[exn:.+]] = load ptr, ptr %exn.slot, align 8

0 commit comments

Comments
 (0)