https://github.com/Andres-Salamanca created 
https://github.com/llvm/llvm-project/pull/173162

This PR upstreams support for the co_yield expression by emitting a cir.await 
op with the yield kind.

>From 111669998908fd162925c216e3a2850f13cd6b87 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Sat, 20 Dec 2025 13:15:55 -0500
Subject: [PATCH] [CIR] Upstream support for coroutine co_yield expression

---
 clang/include/clang/CIR/MissingFeatures.h  |  1 -
 clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp  |  9 +++-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp |  5 ++-
 clang/lib/CIR/CodeGen/CIRGenFunction.h     |  4 ++
 clang/test/CIR/CodeGen/coro-task.cpp       | 50 ++++++++++++++++++++++
 5 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index acfc937a11993..cc0d2579d176b 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 60884aefbfb1f..210e13af7eb35 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -165,10 +165,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 254a8c5883d48..5c178c9265bb2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1656,6 +1656,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: }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to