[clang] [CIR] Add token.none and fix coro.end signature (PR #214125)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 9 11:01:49 PDT 2026
https://github.com/Andres-Salamanca updated https://github.com/llvm/llvm-project/pull/214125
>From 9a4c6cf642bbc036e39a6a0cea190c1ecece0ab6 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <andrealebarbaritos at gmail.com>
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 d0f3c9ee6715f..6b33c84d78b75 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4906,8 +4906,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
@@ -8735,6 +8735,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 9f8454309f13a..3783cbec3d866 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1887,8 +1887,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 717bf5e2e741e..dd8847176b92e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5414,6 +5414,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 0e3f02b16a42d6cd0049ae99fde4621dfd73719a Mon Sep 17 00:00:00 2001
From: Andres Salamanca <andrealebarbaritos at gmail.com>
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 6b33c84d78b75..3092e542fd71c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -8744,9 +8744,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.
More information about the cfe-commits
mailing list