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
