https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/194027
>From 7ba981f976cf0ef4d7b982409ed526c2111ba276 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Fri, 24 Apr 2026 21:07:58 +0200 Subject: [PATCH 1/2] [CIR] Implement CoawaitExpr for ComplexType --- clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp | 10 ++-- clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 3 +- clang/lib/CIR/CodeGen/CIRGenValue.h | 2 + clang/test/CIR/CodeGen/coro-task.cpp | 59 +++++++++++++++++++++ 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp index 12408b7c59458..0bc198f07e8d8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp @@ -558,12 +558,12 @@ emitSuspendExpression(CIRGenFunction &cgf, CGCoroData &coro, if (!awaitRes.rv.isIgnored()) { // Create the alloca in the block before the scope wrapping // cir.await. + mlir::Value value = awaitRes.rv.getAnyValue(); tmpResumeRValAddr = cgf.emitAlloca( - "__coawait_resume_rval", awaitRes.rv.getValue().getType(), loc, - CharUnits::One(), + "__coawait_resume_rval", value.getType(), loc, CharUnits::One(), builder.getBestAllocaInsertPoint(scopeParentBlock)); // Store the rvalue so we can reload it before the promise call. - builder.CIRBaseBuilderTy::createStore(loc, awaitRes.rv.getValue(), + builder.CIRBaseBuilderTy::createStore(loc, value, tmpResumeRValAddr); } } @@ -614,7 +614,9 @@ static RValue emitSuspendExpr(CIRGenFunction &cgf, // once we have a testcase and prove all pieces work. cgf.cgm.errorNYI("emitSuspendExpr Aggregate"); } else { // complex - cgf.cgm.errorNYI("emitSuspendExpr Complex"); + rval = RValue::getComplex(cir::LoadOp::create( + cgf.getBuilder(), scopeLoc, rval.getComplexValue().getType(), + tmpResumeRValAddr)); } return rval; } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index b359c2bd719e4..6a26b2c987f3e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -86,8 +86,7 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { return Visit(pe->getReplacement()); } mlir::Value VisitCoawaitExpr(CoawaitExpr *s) { - cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoawaitExpr"); - return {}; + return cgf.emitCoawaitExpr(*s).getComplexValue(); } mlir::Value VisitCoyieldExpr(CoyieldExpr *s) { cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoyieldExpr"); diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h index e70dac5851189..89e25927ef792 100644 --- a/clang/lib/CIR/CodeGen/CIRGenValue.h +++ b/clang/lib/CIR/CodeGen/CIRGenValue.h @@ -59,6 +59,8 @@ class RValue { return value; } + mlir::Value getAnyValue() const { return value; } + /// Return the value of this complex value. mlir::Value getComplexValue() const { assert(isComplex() && "Not a complex!"); diff --git a/clang/test/CIR/CodeGen/coro-task.cpp b/clang/test/CIR/CodeGen/coro-task.cpp index 2874009157f88..46d7cde18b047 100644 --- a/clang/test/CIR/CodeGen/coro-task.cpp +++ b/clang/test/CIR/CodeGen/coro-task.cpp @@ -839,3 +839,62 @@ folly::coro::Task<int> co_return_with_dtor(int flag) { // OGCG: cleanup4: // OGCG: call void @_ZN7HasDtorD1Ev({{.*}} %[[LOCAL]]) // OGCG: br label %coro.final + +folly::coro::Task<int __complex__> fetchData() noexcept { + int __complex__ a; + co_return a; +} + +folly::coro::Task<int __complex__> complex_co_await() noexcept { + co_await fetchData(); +} + +// CIR: cir.func coroutine {{.*}} @_Z16complex_co_awaitv + +// CIR: %[[COMPLEX_ADDR:.*]] = cir.alloca !rec_folly3A3Acoro3A3ATask3C_Complex_int3E, !cir.ptr<!rec_folly3A3Acoro3A3ATask3C_Complex_int3E>, ["ref.tmp1"] +// CIR: %[[RESUME_VAL_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["__coawait_resume_rval"] + +// CIR: cir.cleanup.scope { +// CIR: cir.await(init, ready : { +// CIR: }, suspend : { +// CIR: }, resume : { +// CIR: },) + +// CIR: cir.coro.body { +// CIR: %[[CALL:.*]] = cir.call @_Z9fetchDatav() nothrow : () -> !rec_folly3A3Acoro3A3ATask3C_Complex_int3E +// CIR: cir.store {{.*}} %[[CALL]], %[[COMPLEX_ADDR]] : !rec_folly3A3Acoro3A3ATask3C_Complex_int3E, !cir.ptr<!rec_folly3A3Acoro3A3ATask3C_Complex_int3E> + +// CIR: cir.await(user, ready : { +// CIR: }, suspend : { +// CIR: }, resume : { +// CIR: %[[RESUME_VAL:.*]] = cir.call @_ZN5folly4coro4TaskICiE12await_resumeEv(%[[COMPLEX_ADDR]]) : (!cir.ptr<!rec_folly3A3Acoro3A3ATask3C_Complex_int3E> {llvm.align = 1 : i64, llvm.dereferenceable = 1 : i64, llvm.nonnull, llvm.noundef}) -> (!cir.complex<!s32i> {llvm.noundef}) +// CIR: cir.store %[[RESUME_VAL]], %[[RESUME_VAL_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>> +// CIR: },) +// CIR: %[[V:.*]] = cir.load %[[RESUME_VAL_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: cir.yield +// CIR: } + +// CIR: } cleanup normal { +// CIR: } + +// OGCG: define dso_local void @_Z16complex_co_awaitv() + +// OGCG: %[[RESUME_VAL_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[RESUME_REAL_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[RESUME_IMAG_ADDR:.*]] = alloca i32, align 4 + +// OGCG: coro.init: +// OGCG: await.ready: +// OGCG: %[[RESUME_VAL:.*]] = call noundef i64 @_ZN5folly4coro4TaskICiE12await_resumeEv(ptr noundef nonnull align 1 dereferenceable(1) %{{.*}}) +// OGCG: store i64 %[[RESUME_VAL]], ptr %[[RESUME_VAL_ADDR]], align 4 +// OGCG: %[[RESUME_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESUME_VAL_ADDR]], i32 0, i32 0 +// OGCG: %[[RESUME_REAL:.*]] = load i32, ptr %[[RESUME_REAL_PTR]], align 4 +// OGCG: store i32 %[[RESUME_REAL]], ptr %[[RESUME_REAL_ADDR]], align 4 +// OGCG: %[[RESUME_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[RESUME_VAL_ADDR]], i32 0, i32 1 +// OGCG: %[[RESUME_IMAG:.*]] = load i32, ptr %[[RESUME_IMAG_PTR]], align 4 +// OGCG: store i32 %[[RESUME_IMAG]], ptr %[[RESUME_IMAG_ADDR]], align 4 +// OGCG: br label %[[CLEANUP_FROM_AWAIT_READY:.*]] + +// OGCG: [[CLEANUP_CONT:.*]]: +// OGCG: %[[RESUME_REAL:.*]] = load i32, ptr %[[RESUME_REAL_ADDR]], align 4 +// OGCG: %[[RESUME_IMAG:.*]] = load i32, ptr %[[RESUME_IMAG_ADDR]], align 4 >From c9e465939b099c5d574b78fe0057641f35a39a6c Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Thu, 7 May 2026 19:48:03 +0200 Subject: [PATCH 2/2] Remove anyValue and switch on the kind --- clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp | 12 +++++++++++- clang/lib/CIR/CodeGen/CIRGenValue.h | 2 -- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp index 0bc198f07e8d8..870015c844a6d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp @@ -558,7 +558,17 @@ emitSuspendExpression(CIRGenFunction &cgf, CGCoroData &coro, if (!awaitRes.rv.isIgnored()) { // Create the alloca in the block before the scope wrapping // cir.await. - mlir::Value value = awaitRes.rv.getAnyValue(); + mlir::Value value; + RValue rv = awaitRes.rv; + if (rv.isScalar()) { + value = rv.getValue(); + } else if (rv.isComplex()) { + value = rv.getComplexValue(); + } else { + cgf.cgm.errorNYI("emitSuspendExpression: Aggregate value"); + return; + } + tmpResumeRValAddr = cgf.emitAlloca( "__coawait_resume_rval", value.getType(), loc, CharUnits::One(), builder.getBestAllocaInsertPoint(scopeParentBlock)); diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h index 89e25927ef792..e70dac5851189 100644 --- a/clang/lib/CIR/CodeGen/CIRGenValue.h +++ b/clang/lib/CIR/CodeGen/CIRGenValue.h @@ -59,8 +59,6 @@ class RValue { return value; } - mlir::Value getAnyValue() const { return value; } - /// Return the value of this complex value. mlir::Value getComplexValue() const { assert(isComplex() && "Not a complex!"); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
