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
