[clang] ba2eaa9 - [CIR] Upstream support for coroutine co_yield expression (#173162)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 14 19:04:11 PST 2026
Author: Andres-Salamanca
Date: 2026-01-14T22:04:07-05:00
New Revision: ba2eaa9f61f0043d4aa442403cd09ebe75c3f5a6
URL: https://github.com/llvm/llvm-project/commit/ba2eaa9f61f0043d4aa442403cd09ebe75c3f5a6
DIFF: https://github.com/llvm/llvm-project/commit/ba2eaa9f61f0043d4aa442403cd09ebe75c3f5a6.diff
LOG: [CIR] Upstream support for coroutine co_yield expression (#173162)
This PR upstreams support for the co_yield expression by emitting a
cir.await op with the yield kind.
Added:
Modified:
clang/include/clang/CIR/MissingFeatures.h
clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
clang/lib/CIR/CodeGen/CIRGenFunction.h
clang/test/CIR/CodeGen/coro-task.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 1b54887e62ff0..2135f6cc7bbc9 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -153,7 +153,6 @@ struct MissingFeatures {
static bool emitBodyAndFallthrough() { return false; }
static bool coroOutsideFrameMD() { return false; }
static bool coroCoReturn() { return false; }
- static bool coroCoYield() { return false; }
static bool coroutineExceptions() { return false; };
// Various handling of deferred processing in CIRGenModule.
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 9251106a641b1..db3bdec436b94 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -418,7 +418,7 @@ emitSuspendExpression(CIRGenFunction &cgf, CGCoroData &coro,
// FIXME(cir): the alloca for the resume expr should be placed in the
// enclosing cir.scope instead.
if (forLValue) {
- assert(!cir::MissingFeatures::coroCoYield());
+ awaitRes.lv = cgf.emitLValue(s.getResumeExpr());
} else {
awaitRes.rv =
cgf.emitAnyExpr(s.getResumeExpr(), aggSlot, ignoreResult);
@@ -486,6 +486,13 @@ RValue CIRGenFunction::emitCoawaitExpr(const CoawaitExpr &e,
ignoreResult);
}
+RValue CIRGenFunction::emitCoyieldExpr(const CoyieldExpr &e,
+ AggValueSlot aggSlot,
+ bool ignoreResult) {
+ return emitSuspendExpr(*this, e, cir::AwaitKind::Yield, aggSlot,
+ ignoreResult);
+}
+
mlir::LogicalResult CIRGenFunction::emitCoreturnStmt(CoreturnStmt const &s) {
++curCoro.data->coreturnCount;
curLexScope->setCoreturn();
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 2a4e6d9b89ee4..4ce38f4e0a1f9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -181,10 +181,11 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
return cgf.emitCoawaitExpr(*s).getValue();
}
+
mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
- cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: coyield");
- return {};
+ return cgf.emitCoyieldExpr(*e).getValue();
}
+
mlir::Value VisitUnaryCoawait(const UnaryOperator *e) {
cgf.cgm.errorNYI(e->getSourceRange(), "ScalarExprEmitter: unary coawait");
return {};
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 5fe1d9a4f2b76..98b3f8384fb75 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1666,6 +1666,10 @@ class CIRGenFunction : public CIRGenTypeCache {
RValue emitCoawaitExpr(const CoawaitExpr &e,
AggValueSlot aggSlot = AggValueSlot::ignored(),
bool ignoreResult = false);
+
+ RValue emitCoyieldExpr(const CoyieldExpr &e,
+ AggValueSlot aggSlot = AggValueSlot::ignored(),
+ bool ignoreResult = false);
/// Emit the computation of the specified expression of complex type,
/// returning the result.
mlir::Value emitComplexExpr(const Expr *e);
diff --git a/clang/test/CIR/CodeGen/coro-task.cpp b/clang/test/CIR/CodeGen/coro-task.cpp
index 6cd494317f2d8..d7b06e1f61aa7 100644
--- a/clang/test/CIR/CodeGen/coro-task.cpp
+++ b/clang/test/CIR/CodeGen/coro-task.cpp
@@ -322,3 +322,53 @@ folly::coro::Task<void> silly_coro() {
// CIR: cir.call @_ZN5folly4coro4TaskIvE12promise_type11return_voidEv
// CIR-NOT: cir.call @_ZN5folly4coro4TaskIvE12promise_type11return_voidEv
// CIR: cir.await(final, ready : {
+
+
+folly::coro::Task<void> yield();
+folly::coro::Task<void> yield1() {
+ auto t = yield();
+ co_yield t;
+}
+
+// CHECK: cir.func coroutine {{.*}} @_Z6yield1v() -> !rec_folly3A3Acoro3A3ATask3Cvoid3E
+
+// CIR: cir.await(init, ready : {
+// CIR: }, suspend : {
+// CIR: }, resume : {
+// CIR: },)
+
+// CIR: cir.scope {
+// CIR-NEXT: %[[SUSPEND_PTR:.*]] = cir.alloca ![[SuspendAlways]], !cir.ptr<![[SuspendAlways]]>
+// CIR-NEXT: %[[AWAITER_PTR:.*]] = cir.alloca ![[VoidTask]], !cir.ptr<![[VoidTask]]>
+// CIR-NEXT: %[[CORO_PTR:.*]] = cir.alloca ![[CoroHandleVoid]], !cir.ptr<![[CoroHandleVoid]]>
+// CIR-NEXT: %[[CORO2_PTR:.*]] = cir.alloca ![[CoroHandlePromiseVoid]], !cir.ptr<![[CoroHandlePromiseVoid]]>
+// CIR-NEXT: cir.copy {{.*}} to %[[AWAITER_PTR]] : !cir.ptr<![[VoidTask]]>
+// CIR-NEXT: %[[AWAITER:.*]] = cir.load{{.*}} %[[AWAITER_PTR]] : !cir.ptr<![[VoidTask]]>, ![[VoidTask]]
+// CIR-NEXT: %[[SUSPEND:.*]] = cir.call @_ZN5folly4coro4TaskIvE12promise_type11yield_valueES2_(%{{.+}}, %[[AWAITER]]) nothrow : (!cir.ptr<![[VoidPromisse]]>, ![[VoidTask]]) -> ![[SuspendAlways]]
+// CIR-NEXT: cir.store{{.*}} %[[SUSPEND]], %[[SUSPEND_PTR]] : ![[SuspendAlways]], !cir.ptr<![[SuspendAlways]]>
+// CIR-NEXT: cir.await(yield, ready : {
+// CIR-NEXT: %[[READY:.*]] = cir.scope {
+// CIR-NEXT: %[[A:.*]] = cir.call @_ZNSt14suspend_always11await_readyEv(%[[SUSPEND_PTR]]) nothrow : (!cir.ptr<![[SuspendAlways]]>) -> !cir.bool
+// CIR-NEXT: cir.yield %[[A]] : !cir.bool
+// CIR-NEXT: } : !cir.bool
+// CIR-NEXT: cir.condition(%[[READY]])
+// CIR-NEXT: }, suspend : {
+// CIR-NEXT: %[[CORO2:.*]] = cir.call @_ZNSt16coroutine_handleIN5folly4coro4TaskIvE12promise_typeEE12from_addressEPv(%9) nothrow : (!cir.ptr<!void>) -> ![[CoroHandlePromiseVoid]]
+// CIR-NEXT: cir.store{{.*}} %[[CORO2]], %[[CORO2_PTR]] : ![[CoroHandlePromiseVoid]], !cir.ptr<![[CoroHandlePromiseVoid]]>
+// CIR-NEXT: %[[B:.*]] = cir.load{{.*}} %[[CORO2_PTR]] : !cir.ptr<![[CoroHandlePromiseVoid]]>, ![[CoroHandlePromiseVoid]]
+// CIR-NEXT: cir.call @_ZNSt16coroutine_handleIvEC1IN5folly4coro4TaskIvE12promise_typeEEES_IT_E(%[[CORO_PTR]], %[[B]]) nothrow : (!cir.ptr<![[CoroHandleVoid]]>, ![[CoroHandlePromiseVoid]]) -> ()
+// CIR-NEXT: %[[C:.*]] = cir.load{{.*}} %[[CORO_PTR]] : !cir.ptr<![[CoroHandleVoid]]>, ![[CoroHandleVoid]]
+// CIR-NEXT: cir.call @_ZNSt14suspend_always13await_suspendESt16coroutine_handleIvE(%[[SUSPEND_PTR]], %[[C]]) nothrow : (!cir.ptr<![[SuspendAlways]]>, ![[CoroHandleVoid]]) -> ()
+// CIR-NEXT: cir.yield
+// CIR-NEXT: }, resume : {
+// CIR-NEXT: cir.call @_ZNSt14suspend_always12await_resumeEv(%[[SUSPEND_PTR]]) nothrow : (!cir.ptr<![[SuspendAlways]]>) -> ()
+// CIR-NEXT: cir.yield
+// CIR-NEXT: },)
+// CIR-NEXT: }
+
+// CIR: cir.await(final, ready : {
+// CIR: }, suspend : {
+// CIR: }, resume : {
+// CIR: },)
+
+// CHECK: }
More information about the cfe-commits
mailing list