https://github.com/Andres-Salamanca updated 
https://github.com/llvm/llvm-project/pull/214125

>From 57c6f89dcdbb7da9ce76cb87961b768015f1872e Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Tue, 4 Aug 2026 22:24:35 -0500
Subject: [PATCH 1/2] [CIR] Add token.none and fix coro.end signature

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 22 +++++++++++++++++--
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |  6 ++---
 clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp     | 21 ++++++++++++------
 clang/lib/CIR/CodeGen/CIRGenFunction.h        |  3 +--
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  6 +++++
 .../CIR/CodeGenCoroutines/coro-builtins.cpp   |  6 +++--
 .../test/CIR/CodeGenCoroutines/coro-task.cpp  |  7 +++---
 7 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 49ecec207cd45..fca0f3f207fd3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4905,8 +4905,8 @@ def CIR_CoroBeginOp : CIR_CoroIntrinsicOp<"begin",
 
//===----------------------------------------------------------------------===//
 
 def CIR_CoroEndOp : CIR_CoroIntrinsicOp<"end",
-    (ins CIR_VoidPtrType:$handle, CIR_AnyBoolType:$unwind),
-    (outs CIR_AnyBoolType:$result)> {
+    (ins CIR_VoidPtrType:$handle, CIR_AnyBoolType:$unwind, Token:$resultToken),
+    (outs), [TokenConsumerTrait]> {
   let summary = "Represents llvm.coro.end";
   let description = [{
     Marks a point at which a coroutine must be suspended or destroyed for the
@@ -8734,6 +8734,24 @@ def CIR_ConstructCatchParamOp : 
CIR_Op<"construct_catch_param", [
   let hasLLVMLowering = false;
 }
 
+//===----------------------------------------------------------------------===//
+// TokenNoneOp
+//===----------------------------------------------------------------------===//
+
+def CIR_TokenNoneOp : CIR_Op<"token.none", [
+  Pure, TokenProducerTrait
+]> {
+  let summary = "Produces an empty token value.";
+  let description = [{
+    MLIR does not have a way to represent the LLVM IR `none` token literal.
+    Like the LLVM dialect, CIR provides an operation that produces a token
+    value, which can later be lowered to `llvm::ConstantTokenNone`.
+  }];
+
+  let results = (outs Token:$result);
+  let assemblyFormat = "attr-dict";
+}
+
 
//===----------------------------------------------------------------------===//
 // Atomic operations
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 1efe2b81d5cae..fc8ed339ffd88 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1388,7 +1388,8 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
     return coroBeg ? RValue::get(coroBeg.getResult())
                    : getUndefRValue(e->getType());
   }
-
+  case Builtin::BI__builtin_coro_end:
+    return RValue::get(emitCoroEndBuiltinCall(e).getResultToken());
   case Builtin::BI__builtin_coro_promise:
     cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_promise NYI");
     return getUndefRValue(e->getType());
@@ -1404,9 +1405,6 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BI__builtin_coro_done:
     cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_done NYI");
     return getUndefRValue(e->getType());
-  case Builtin::BI__builtin_coro_end:
-    cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_end NYI");
-    return getUndefRValue(e->getType());
   case Builtin::BI__builtin_coro_suspend:
     cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_suspend NYI");
     return getUndefRValue(e->getType());
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 9111c2ac98863..8abf9cd999c67 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -274,11 +274,16 @@ cir::CoroBeginOp 
CIRGenFunction::emitCoroBeginBuiltinCall(const CallExpr *e) {
   return coroBegin;
 }
 
-cir::CoroEndOp CIRGenFunction::emitCoroEndBuiltinCall(mlir::Location loc,
-                                                      mlir::Value nullPtr) {
-  return cir::CoroEndOp::create(
-      cgm.getBuilder(), loc,
-      mlir::ValueRange{nullPtr, builder.getBool(false, loc)});
+cir::CoroEndOp CIRGenFunction::emitCoroEndBuiltinCall(const CallExpr *e) {
+
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  CIRGenBuilderTy &builder = cgm.getBuilder();
+  llvm::SmallVector<mlir::Value, 3> args;
+  for (const Expr *arg : e->arguments())
+    args.push_back(emitScalarExpr(arg));
+  auto tkNone = cir::TokenNoneOp::create(builder, loc);
+  args.push_back(tkNone.getResult());
+  return cir::CoroEndOp::create(builder, loc, {}, args);
 }
 
 cir::CoroFreeOp CIRGenFunction::emitCoroFreeBuiltin(const CallExpr *e) {
@@ -504,10 +509,12 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt 
&s) {
       }
     }
   }
+
+  auto tkNone = cir::TokenNoneOp::create(cgm.getBuilder(), openCurlyLoc);
   cir::CoroEndOp::create(
       cgm.getBuilder(), openCurlyLoc,
-      mlir::ValueRange{builder.getNullPtr(builder.getVoidPtrTy(), 
openCurlyLoc),
-                       builder.getBool(false, openCurlyLoc)});
+      builder.getNullPtr(builder.getVoidPtrTy(), openCurlyLoc),
+      builder.getBool(false, openCurlyLoc), tkNone.getResult());
   if (auto *ret = cast_or_null<ReturnStmt>(s.getReturnStmt())) {
     // Since we already emitted the return value above, so we shouldn't
     // emit it again here.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 6c9bccf50b360..c96662ea46ac4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1877,8 +1877,7 @@ class CIRGenFunction : public CIRGenTypeCache {
   void emitConstructorBody(FunctionArgList &args);
 
   mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
-  cir::CoroEndOp emitCoroEndBuiltinCall(mlir::Location loc,
-                                        mlir::Value nullPtr);
+  cir::CoroEndOp emitCoroEndBuiltinCall(const CallExpr *e);
   cir::CoroIdOp emitCoroIDBuiltinCall(const CallExpr *e);
   cir::CoroAllocOp emitCoroAllocBuiltinCall(const CallExpr *e);
   cir::CoroBeginOp emitCoroBeginBuiltinCall(const CallExpr *e);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4e923f2bcee28..1d4da8ae7f256 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5386,6 +5386,12 @@ mlir::LogicalResult 
CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMTokenNoneOpLowering::matchAndRewrite(
+    cir::TokenNoneOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  return mlir::failure();
+}
+
 mlir::LogicalResult CIRToLLVMCoroFreeOpLowering::matchAndRewrite(
     cir::CoroFreeOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
index f92f4d996c460..de1fe9126eb77 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
@@ -43,8 +43,10 @@ void f(int n) {
   __builtin_coro_free(__builtin_coro_frame());
   // CIR: cir.coro.intrinsic.free(%[[COROID]], %[[FRAME]])
 
-  // TODO(CIR):
-  //__builtin_coro_end(__builtin_coro_frame(), 0);
+  __builtin_coro_end(__builtin_coro_frame(), false);
+  // CIR: %[[FALSE:.*]] = cir.const #false
+  // CIR: %[[TK_NONE:.*]] = cir.token.none
+  // CIR: cir.coro.intrinsic.end(%[[FRAME]], %[[FALSE]], %[[TK_NONE]]) : 
(!cir.ptr<!void>, !cir.bool, token)
 
   // TODO(CIR):
   //__builtin_coro_suspend(1);
diff --git a/clang/test/CIR/CodeGenCoroutines/coro-task.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-task.cpp
index d0ba8c153bdbb..8335ab0377073 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-task.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-task.cpp
@@ -212,9 +212,10 @@ VoidTask silly_task() {
 
 // Call builtin coro end and return
 
-// CIR: %[[CoroEndArg0:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
+// CIR: %[[TK_NONE:.*]] = cir.token.none
 // CIR: %[[CoroEndArg1:.*]] = cir.const #false
-// CIR: = cir.coro.intrinsic.end(%[[CoroEndArg0]], %[[CoroEndArg1]]) : 
(!cir.ptr<!void>, !cir.bool) -> !cir.bool
+// CIR: %[[CoroEndArg0:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
+// CIR: cir.coro.intrinsic.end(%[[CoroEndArg0]], %[[CoroEndArg1]], 
%[[TK_NONE]]) : (!cir.ptr<!void>, !cir.bool, token)
 
 // CIR: %[[Tmp1:.*]] = cir.load{{.*}} %[[VoidTaskAddr]]
 // CIR: cir.return %[[Tmp1]]
@@ -402,7 +403,7 @@ folly::coro::Task<void> yield1() {
 // CIR:   cir.yield
 // CIR: } cleanup  normal {
 // CIR: }
-// CIR: = cir.coro.intrinsic.end(%{{.*}}, %{{.*}})
+// CIR: cir.coro.intrinsic.end(%{{.*}}, %{{.*}}, %{{.*}})
 // CIR: %[[RETLOAD:.*]] = cir.load{{.*}} %[[RETVAL]]
 // CIR: cir.return %[[RETLOAD]]
 // CIR: }

>From d46fb8e47b1d9982d3b18dc9956babdb84a5bb07 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Sun, 9 Aug 2026 12:05:00 -0500
Subject: [PATCH 2/2] Address review comments

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td | 5 ++---
 clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp    | 7 +++----
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index fca0f3f207fd3..21d71ebf2fde5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -8743,9 +8743,8 @@ def CIR_TokenNoneOp : CIR_Op<"token.none", [
 ]> {
   let summary = "Produces an empty token value.";
   let description = [{
-    MLIR does not have a way to represent the LLVM IR `none` token literal.
-    Like the LLVM dialect, CIR provides an operation that produces a token
-    value, which can later be lowered to `llvm::ConstantTokenNone`.
+    Produces a `none` token value, mirroring LLVM IR's `none` token
+    literal. Lowers to `llvm::ConstantTokenNone`.
   }];
 
   let results = (outs Token:$result);
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 8abf9cd999c67..275f120f812f1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -281,8 +281,7 @@ cir::CoroEndOp CIRGenFunction::emitCoroEndBuiltinCall(const 
CallExpr *e) {
   llvm::SmallVector<mlir::Value, 3> args;
   for (const Expr *arg : e->arguments())
     args.push_back(emitScalarExpr(arg));
-  auto tkNone = cir::TokenNoneOp::create(builder, loc);
-  args.push_back(tkNone.getResult());
+  args.push_back(cir::TokenNoneOp::create(builder, loc));
   return cir::CoroEndOp::create(builder, loc, {}, args);
 }
 
@@ -510,11 +509,11 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt 
&s) {
     }
   }
 
-  auto tkNone = cir::TokenNoneOp::create(cgm.getBuilder(), openCurlyLoc);
   cir::CoroEndOp::create(
       cgm.getBuilder(), openCurlyLoc,
       builder.getNullPtr(builder.getVoidPtrTy(), openCurlyLoc),
-      builder.getBool(false, openCurlyLoc), tkNone.getResult());
+      builder.getBool(false, openCurlyLoc),
+      cir::TokenNoneOp::create(cgm.getBuilder(), openCurlyLoc));
   if (auto *ret = cast_or_null<ReturnStmt>(s.getReturnStmt())) {
     // Since we already emitted the return value above, so we shouldn't
     // emit it again here.

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

Reply via email to