[clang] [CIR] Change previous coroutine builtins to have their own coro intrinsic ops (PR #211699)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 26 19:41:32 PDT 2026
https://github.com/Andres-Salamanca updated https://github.com/llvm/llvm-project/pull/211699
>From cd87691f4eda3bd7330350a7e9ebe0bb491940d2 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <andrealebarbaritos at gmail.com>
Date: Thu, 23 Jul 2026 19:07:57 -0500
Subject: [PATCH 1/3] [CIR] Change previous coroutine builtins to have their
own coro intrinsic ops
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 125 +++++++++++
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 48 +++--
clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp | 204 +++++++++---------
clang/lib/CIR/CodeGen/CIRGenFunction.h | 15 +-
clang/lib/CIR/CodeGen/CIRGenModule.h | 6 -
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 42 ++++
clang/test/CIR/CodeGen/coro-builtins-err.cpp | 10 +
clang/test/CIR/CodeGen/coro-builtins.cpp | 51 +++++
.../test/CIR/CodeGenCoroutines/coro-task.cpp | 22 +-
9 files changed, 378 insertions(+), 145 deletions(-)
create mode 100644 clang/test/CIR/CodeGen/coro-builtins-err.cpp
create mode 100644 clang/test/CIR/CodeGen/coro-builtins.cpp
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index b0f654a54bacd..e62bc98c4a341 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4702,6 +4702,131 @@ def CIR_CoReturnOp : CIR_Op<"co_return", [
let hasLLVMLowering = false;
}
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsics
+//===----------------------------------------------------------------------===//
+
+class CIR_CoroIntrinsicOp<string mnem, dag ins, dag outs,
+ list<Trait> traits = []>
+ : CIR_Op<"coro.intrinsic." # mnem, traits> {
+ let hasLLVMLowering = 1;
+ let arguments = ins;
+ let results = outs;
+
+ let assemblyFormat = [{
+ `(` operands `)` `:` functional-type(operands, results) attr-dict
+ }];
+}
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic IdOp
+//===----------------------------------------------------------------------===//
+
+// TODO: This operation should return an MLIR `token` once the type becomes
+// available. `CIR_UInt32` is used as a temporary placeholder.
+def CIR_CoroIntrinsicIdOp : CIR_CoroIntrinsicOp<"id",
+ (ins CIR_AnyIntType:$align, CIR_VoidPtrType:$promise,
+ CIR_VoidPtrType:$coroaddr, CIR_VoidPtrType:$fnaddrs),
+ (outs CIR_UInt32:$result)> {
+ let summary = "Represents llvm.coro.id";
+ let description = [{
+ Marks the beginning of a coroutine's lifetime and identifies it to the
+ rest of the coroutine intrinsics. Takes the required alignment of the
+ coroutine frame, a pointer to the coroutine promise (or null if none),
+ the address of the coroutine function itself, and an opaque pointer used
+ by the frontend to convey additional information to the coroutine
+ lowering passes (or null).
+
+ The result is a token that must be passed to every other
+ `coro.intrinsic.*` operation associated with this coroutine
+ (`coro.alloc`, `coro.begin`, `coro.free`, etc.), tying them all to the
+ same coroutine instance.
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic AllocOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroIntrinsicAllocOp : CIR_CoroIntrinsicOp<"alloc",
+ (ins CIR_AnyIntType:$id),
+ (outs CIR_AnyBoolType:$result)> {
+ let summary = "Represents llvm.coro.alloc";
+ let description = [{
+ Queries whether the coroutine identified by `id` needs a dynamically
+ allocated frame. Returns `true` if the coroutine frame must be allocated,
+ or `false` otherwise.
+ }];
+}
+
+// TODO: Replace the `id` operand with MLIR's `token` type once it becomes
+// available. This operand corresponds to the token produced by `llvm.coro.id`.
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic BeginOp
+//===----------------------------------------------------------------------===//
+def CIR_CoroIntrinsicBeginOp : CIR_CoroIntrinsicOp<"begin",
+ (ins CIR_UInt32:$id, CIR_VoidPtrType:$coroframeAddr),
+ (outs CIR_VoidPtrType:$result)> {
+ let summary = "Represents llvm.coro.begin";
+ let description = [{
+ Initializes the coroutine frame using `coroframeAddr`. `id` is the token
+ from `coro.intrinsic.id`, and `coroframeAddr` points to the memory used
+ for the coroutine frame. Returns the coroutine handle.
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic EndOp
+//===----------------------------------------------------------------------===//
+def CIR_CoroIntrinsicEndOp : CIR_CoroIntrinsicOp<"end",
+ (ins CIR_VoidPtrType:$handle, CIR_AnyBoolType:$unwind),
+ (outs CIR_AnyBoolType:$result)> {
+ let summary = "Represents llvm.coro.end";
+ let description = [{
+ Marks a point at which a coroutine must be suspended or destroyed for the
+ last time, e.g. right before the coroutine returns control to its caller
+ for the final time, or along an exceptional unwind path. `handle` is the
+ coroutine handle produced by `coro.intrinsic.begin`, and `unwind`
+ indicates whether this occurrence of `coro.intrinsic.end` lies on the
+ unwind path (`true`) or the normal control-flow path (`false`).
+ }];
+}
+
+// TODO: Replace the `id` operand with MLIR's `token` type once it becomes
+// available. This operand corresponds to the token produced by `llvm.coro.id`.
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic FreeOp
+//===----------------------------------------------------------------------===//
+def CIR_CoroIntrinsicFreeOp : CIR_CoroIntrinsicOp<"free",
+ (ins CIR_AnyIntType:$id, CIR_VoidPtrType:$coroframe),
+ (outs CIR_VoidPtrType:$result)> {
+ let summary = "Represents llvm.coro.free";
+ let description = [{
+ Given the coroutine identified by `id` and its frame pointer `coroframe`
+ (the handle from `coro.intrinsic.begin`), returns the pointer that must
+ be passed to the deallocation function to free the coroutine frame, or a
+ null pointer if the coroutine frame was not dynamically allocated.
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic SizeOp
+//===----------------------------------------------------------------------===//
+def CIR_CoroIntrinsicSizeOp : CIR_CoroIntrinsicOp<"size",
+ (ins), (outs CIR_UInt64:$result)> {
+ let summary = "Represents llvm.coro.size";
+ let description = [{
+ Returns the size, in bytes, of the coroutine frame.
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic IsInRampOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroIntrinsicIsInRampOp : CIR_CoroIntrinsicOp<"is_in_ramp",
+ (ins), (outs CIR_AnyBoolType:$result), [Pure]> {
+ let summary = "";
+}
//===----------------------------------------------------------------------===//
// CopyOp
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index d67134583d48a..36bdefc79a2c8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1361,34 +1361,54 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
return emitRotate(e, /*isRotateLeft=*/false);
case Builtin::BI__builtin_coro_id:
+ return RValue::get(emitCoroIDBuiltinCall(e).getResult());
+ case Builtin::BI__builtin_coro_alloc: {
+ cir::CoroIntrinsicAllocOp coroAlloc = emitCoroAllocBuiltinCall(e);
+ return coroAlloc ? RValue::get(coroAlloc.getResult())
+ : getUndefRValue(e->getType());
+ }
+ case Builtin::BI__builtin_coro_begin: {
+ cir::CoroIntrinsicBeginOp coroBeg = emitCoroBeginBuiltinCall(e);
+ return coroBeg ? RValue::get(coroBeg.getResult())
+ : getUndefRValue(e->getType());
+ }
+
case Builtin::BI__builtin_coro_promise:
+ cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_promise NYI");
+ return getUndefRValue(e->getType());
case Builtin::BI__builtin_coro_resume:
+ cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_resume NYI");
+ return getUndefRValue(e->getType());
case Builtin::BI__builtin_coro_noop:
+ cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_noop NYI");
+ return getUndefRValue(e->getType());
case Builtin::BI__builtin_coro_destroy:
+ cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_destroy NYI");
+ return getUndefRValue(e->getType());
case Builtin::BI__builtin_coro_done:
- case Builtin::BI__builtin_coro_alloc:
- case Builtin::BI__builtin_coro_begin:
+ 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());
case Builtin::BI__builtin_coro_align:
- cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_id like NYI");
+ cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_align NYI");
return getUndefRValue(e->getType());
case Builtin::BI__builtin_coro_frame: {
return emitCoroutineFrame();
}
- case Builtin::BI__builtin_coro_free:
- return RValue::get(emitCoroFreeBuiltin(e).getResult());
+ case Builtin::BI__builtin_coro_free: {
+ cir::CoroIntrinsicFreeOp coroFree = emitCoroFreeBuiltin(e);
+ return coroFree ? RValue::get(coroFree.getResult())
+ : getUndefRValue(e->getType());
+ }
+
case Builtin::BI__builtin_coro_size: {
- GlobalDecl gd{fd};
- mlir::Type ty = cgm.getTypes().getFunctionType(
- cgm.getTypes().arrangeGlobalDeclaration(gd));
- const auto *nd = cast<NamedDecl>(gd.getDecl());
- cir::FuncOp fnOp =
- cgm.getOrCreateCIRFunction(nd->getName(), ty, gd, /*ForVTable=*/false);
- fnOp.setBuiltin(true);
- return emitCall(e->getCallee()->getType(), CIRGenCallee::forDirect(fnOp), e,
- returnValue);
+ return RValue::get(emitCoroSizeBuiltinCall(e).getResult());
}
case Builtin::BI__builtin_constant_p: {
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 3dd71a8ad3b6c..2aa199c347152 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -28,7 +28,7 @@ struct clang::CIRGen::CGCoroData {
cir::AwaitKind currentAwaitKind = cir::AwaitKind::Init;
// Stores the __builtin_coro_id emitted in the function so that we can supply
// it as the first argument to other builtins.
- cir::CallOp coroId = nullptr;
+ cir::CoroIntrinsicIdOp coroId = nullptr;
// Stores the result of __builtin_coro_begin call.
mlir::Value coroBegin = nullptr;
@@ -42,13 +42,18 @@ struct clang::CIRGen::CGCoroData {
// Stores the last emitted coro.free for the deallocate expressions, we use it
// to wrap dealloc code with if(auto mem = coro.free) dealloc(mem).
- cir::CallOp lastCoroFree = nullptr;
+ cir::CoroIntrinsicFreeOp lastCoroFree = nullptr;
// A temporary bool alloca that stores whether 'await_resume' threw an
// exception. If it did, 'true' is stored in this variable, and the coroutine
// body must be skipped. If the promise type does not define an exception
// handler, this is null.
Address resumeEHVar = Address::invalid();
+ //
+ // If coro.id came from the builtin, remember the expression to give better
+ // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
+ // EmitCoroutineBody.
+ CallExpr const *coroIdExpr = nullptr;
};
// Defining these here allows to keep CGCoroData private to this file.
@@ -139,7 +144,7 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup {
}
CIRGenBuilderTy &builder = cgf.getBuilder();
- cir::CallOp coroFree = cgf.curCoro.data->lastCoroFree;
+ cir::CoroIntrinsicFreeOp coroFree = cgf.curCoro.data->lastCoroFree;
if (!coroFree) {
cgf.cgm.error(deallocate->getBeginLoc(),
@@ -182,11 +187,22 @@ RValue CIRGenFunction::emitCoroutineFrame() {
static void createCoroData(CIRGenFunction &cgf,
CIRGenFunction::CGCoroInfo &curCoro,
- cir::CallOp coroId) {
- assert(!curCoro.data && "EmitCoroutineBodyStatement called twice?");
+ cir::CoroIntrinsicIdOp coroId,
+ CallExpr const *coroIdExpr = nullptr) {
+
+ if (curCoro.data) {
+ if (curCoro.data->coroIdExpr)
+ cgf.cgm.error(coroIdExpr->getBeginLoc(),
+ "only one __builtin_coro_id can be used in a function");
+ else
+ llvm_unreachable("EmitCoroutineBodyStatement called twice?");
+
+ return;
+ }
curCoro.data = std::make_unique<CGCoroData>();
curCoro.data->coroId = coroId;
+ curCoro.data->coroIdExpr = coroIdExpr;
}
static mlir::LogicalResult
@@ -212,113 +228,84 @@ emitBodyAndFallthrough(CIRGenFunction &cgf, const CoroutineBodyStmt &s,
return mlir::success();
}
-cir::CallOp CIRGenFunction::emitCoroIDBuiltinCall(mlir::Location loc,
- mlir::Value nullPtr) {
- cir::IntType int32Ty = builder.getUInt32Ty();
-
- const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
- unsigned newAlign = ti.getNewAlign() / ti.getCharWidth();
+cir::CoroIntrinsicIdOp
+CIRGenFunction::emitCoroIDBuiltinCall(const CallExpr *e) {
+ mlir::Location loc = getLoc(e->getBeginLoc());
- mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroId);
-
- cir::FuncOp fnOp;
- if (!builtin) {
- fnOp = cgm.createCIRBuiltinFunction(
- loc, cgm.builtinCoroId,
- cir::FuncType::get({int32Ty, voidPtrTy, voidPtrTy, voidPtrTy}, int32Ty),
- /*FD=*/nullptr);
- assert(fnOp && "should always succeed");
- } else {
- fnOp = cast<cir::FuncOp>(builtin);
+ llvm::SmallVector<mlir::Value, 4> args;
+ for (auto const *arg : e->arguments()) {
+ args.push_back(emitScalarExpr(arg));
}
-
- return builder.createCallOp(loc, fnOp,
- mlir::ValueRange{builder.getUInt32(newAlign, loc),
- nullPtr, nullPtr, nullPtr});
+ auto coroId = cir::CoroIntrinsicIdOp::create(cgm.getBuilder(), loc, args);
+ createCoroData(*this, curCoro, coroId, e);
+ return coroId;
}
-cir::CallOp CIRGenFunction::emitCoroAllocBuiltinCall(mlir::Location loc) {
- cir::BoolType boolTy = builder.getBoolTy();
-
- mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroAlloc);
-
- cir::FuncOp fnOp;
- if (!builtin) {
- fnOp = cgm.createCIRBuiltinFunction(loc, cgm.builtinCoroAlloc,
- cir::FuncType::get({uInt32Ty}, boolTy),
- /*fd=*/nullptr);
- assert(fnOp && "should always succeed");
- } else {
- fnOp = cast<cir::FuncOp>(builtin);
+cir::CoroIntrinsicAllocOp
+CIRGenFunction::emitCoroAllocBuiltinCall(const CallExpr *e) {
+ mlir::Location loc = getLoc(e->getBeginLoc());
+ if (!curCoro.data || !curCoro.data->coroId) {
+ cgm.error(e->getBeginLoc(), "this builtin expect that __builtin_coro_id has"
+ " been used earlier in this function");
+ return {};
}
- return builder.createCallOp(
- loc, fnOp, mlir::ValueRange{curCoro.data->coroId.getResult()});
+ return cir::CoroIntrinsicAllocOp::create(
+ cgm.getBuilder(), loc,
+ mlir::ValueRange{curCoro.data->coroId.getResult()});
}
-cir::CallOp
-CIRGenFunction::emitCoroBeginBuiltinCall(mlir::Location loc,
- mlir::Value coroframeAddr) {
- mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroBegin);
-
- cir::FuncOp fnOp;
- if (!builtin) {
- fnOp = cgm.createCIRBuiltinFunction(
- loc, cgm.builtinCoroBegin,
- cir::FuncType::get({uInt32Ty, voidPtrTy}, voidPtrTy),
- /*fd=*/nullptr);
- assert(fnOp && "should always succeed");
- } else {
- fnOp = cast<cir::FuncOp>(builtin);
- }
-
- return builder.createCallOp(
- loc, fnOp,
- mlir::ValueRange{curCoro.data->coroId.getResult(), coroframeAddr});
-}
+cir::CoroIntrinsicBeginOp
+CIRGenFunction::emitCoroBeginBuiltinCall(const CallExpr *e) {
-cir::CallOp CIRGenFunction::emitCoroEndBuiltinCall(mlir::Location loc,
- mlir::Value nullPtr) {
- cir::BoolType boolTy = builder.getBoolTy();
- mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroEnd);
-
- cir::FuncOp fnOp;
- if (!builtin) {
- fnOp = cgm.createCIRBuiltinFunction(
- loc, cgm.builtinCoroEnd,
- cir::FuncType::get({voidPtrTy, boolTy}, boolTy),
- /*fd=*/nullptr);
- assert(fnOp && "should always succeed");
- } else {
- fnOp = cast<cir::FuncOp>(builtin);
+ mlir::Location loc = getLoc(e->getBeginLoc());
+ if (!curCoro.data || !curCoro.data->coroId) {
+ cgm.error(e->getBeginLoc(), "this builtin expect that __builtin_coro_id has"
+ " been used earlier in this function");
+ return {};
+ }
+ llvm::SmallVector<mlir::Value, 2> args;
+ args.push_back(curCoro.data->coroId.getResult());
+ for (auto const *arg : e->arguments()) {
+ args.push_back(emitScalarExpr(arg));
}
+ auto coroBegin =
+ cir::CoroIntrinsicBeginOp::create(cgm.getBuilder(), loc, args);
+ curCoro.data->coroBegin = coroBegin;
+ return coroBegin;
+}
- return builder.createCallOp(
- loc, fnOp, mlir::ValueRange{nullPtr, builder.getBool(false, loc)});
+cir::CoroIntrinsicEndOp
+CIRGenFunction::emitCoroEndBuiltinCall(mlir::Location loc,
+ mlir::Value nullPtr) {
+ return cir::CoroIntrinsicEndOp::create(
+ cgm.getBuilder(), loc,
+ mlir::ValueRange{nullPtr, builder.getBool(false, loc)});
}
-cir::CallOp CIRGenFunction::emitCoroFreeBuiltin(const CallExpr *e) {
- mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroFree);
+cir::CoroIntrinsicFreeOp
+CIRGenFunction::emitCoroFreeBuiltin(const CallExpr *e) {
mlir::Location loc = getLoc(e->getBeginLoc());
- cir::FuncOp fnOp;
- if (!builtin) {
- fnOp = cgm.createCIRBuiltinFunction(
- loc, cgm.builtinCoroFree,
- cir::FuncType::get({uInt32Ty, voidPtrTy}, voidPtrTy),
- /*fd=*/nullptr);
- assert(fnOp && "should always succeed");
- } else {
- fnOp = cast<cir::FuncOp>(builtin);
+ if (!curCoro.data || !curCoro.data->coroId) {
+ cgm.error(e->getBeginLoc(), "this builtin expect that __builtin_coro_id has"
+ " been used earlier in this function");
+ return {};
}
- cir::CallOp coroFree =
- builder.createCallOp(loc, fnOp,
- mlir::ValueRange{curCoro.data->coroId.getResult(),
- curCoro.data->coroBegin});
-
- curCoro.data->lastCoroFree = coroFree;
+ auto coroFree = cir::CoroIntrinsicFreeOp::create(
+ cgm.getBuilder(), loc,
+ mlir::ValueRange{curCoro.data->coroId.getResult(),
+ curCoro.data->coroBegin});
+ if (curCoro.data)
+ curCoro.data->lastCoroFree = coroFree;
return coroFree;
}
+cir::CoroIntrinsicSizeOp
+CIRGenFunction::emitCoroSizeBuiltinCall(const CallExpr *e) {
+ mlir::Location loc = getLoc(e->getBeginLoc());
+ return cir::CoroIntrinsicSizeOp::create(cgm.getBuilder(), loc);
+}
+
static mlir::LogicalResult
coroutineBodyExceptionHelper(CIRGenFunction &cgf, const CoroutineBodyStmt &s) {
@@ -348,12 +335,20 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
auto fn = mlir::cast<cir::FuncOp>(curFn);
fn.setCoroutine(true);
- cir::CallOp coroId = emitCoroIDBuiltinCall(openCurlyLoc, nullPtrCst);
+ const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
+ unsigned newAlign = ti.getNewAlign() / ti.getCharWidth();
+
+ cir::CoroIntrinsicIdOp coroId = cir::CoroIntrinsicIdOp::create(
+ cgm.getBuilder(), openCurlyLoc,
+ mlir::ValueRange{builder.getUInt32(newAlign, openCurlyLoc), nullPtrCst,
+ nullPtrCst, nullPtrCst});
createCoroData(*this, curCoro, coroId);
// Backend is allowed to elide memory allocations, to help it, emit
// auto mem = coro.alloc() ? 0 : ... allocation code ...;
- cir::CallOp coroAlloc = emitCoroAllocBuiltinCall(openCurlyLoc);
+ cir::CoroIntrinsicAllocOp coroAlloc = cir::CoroIntrinsicAllocOp::create(
+ cgm.getBuilder(), openCurlyLoc,
+ mlir::ValueRange{curCoro.data->coroId.getResult()});
// Initialize address of coroutine frame to null
CanQualType astVoidPtrTy = cgm.getASTContext().VoidPtrTy;
@@ -373,11 +368,11 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
loc, emitScalarExpr(s.getAllocate()), storeAddr);
cir::YieldOp::create(builder, loc);
});
- curCoro.data->coroBegin =
- emitCoroBeginBuiltinCall(
- openCurlyLoc,
- cir::LoadOp::create(builder, openCurlyLoc, allocaTy, storeAddr))
- .getResult();
+ curCoro.data->coroBegin = cir::CoroIntrinsicBeginOp::create(
+ cgm.getBuilder(), openCurlyLoc,
+ mlir::ValueRange{
+ curCoro.data->coroId.getResult(),
+ cir::LoadOp::create(builder, openCurlyLoc, allocaTy, storeAddr)});
// Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
if (s.getReturnStmtOnAllocFailure())
@@ -511,9 +506,10 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
}
}
}
-
- emitCoroEndBuiltinCall(
- openCurlyLoc, builder.getNullPtr(builder.getVoidPtrTy(), openCurlyLoc));
+ cir::CoroIntrinsicEndOp::create(
+ cgm.getBuilder(), openCurlyLoc,
+ mlir::ValueRange{builder.getNullPtr(builder.getVoidPtrTy(), openCurlyLoc),
+ builder.getBool(false, 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.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index d88f38eefa99a..e28df42eb08a9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1862,13 +1862,14 @@ class CIRGenFunction : public CIRGenTypeCache {
void emitConstructorBody(FunctionArgList &args);
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
- cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
- cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
- cir::CallOp emitCoroAllocBuiltinCall(mlir::Location loc);
- cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc,
- mlir::Value coroframeAddr);
-
- cir::CallOp emitCoroFreeBuiltin(const CallExpr *e);
+ cir::CoroIntrinsicEndOp emitCoroEndBuiltinCall(mlir::Location loc,
+ mlir::Value nullPtr);
+ cir::CoroIntrinsicIdOp emitCoroIDBuiltinCall(const CallExpr *e);
+ cir::CoroIntrinsicAllocOp emitCoroAllocBuiltinCall(const CallExpr *e);
+ cir::CoroIntrinsicBeginOp emitCoroBeginBuiltinCall(const CallExpr *e);
+
+ cir::CoroIntrinsicSizeOp emitCoroSizeBuiltinCall(const CallExpr *e);
+ cir::CoroIntrinsicFreeOp emitCoroFreeBuiltin(const CallExpr *e);
RValue emitCoroutineFrame();
void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index f5ac70a33aef5..49fa7a236763a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -815,12 +815,6 @@ class CIRGenModule : public CIRGenTypeCache {
bool isLocal = false,
bool assumeConvergent = false);
- static constexpr const char *builtinCoroId = "__builtin_coro_id";
- static constexpr const char *builtinCoroAlloc = "__builtin_coro_alloc";
- static constexpr const char *builtinCoroBegin = "__builtin_coro_begin";
- static constexpr const char *builtinCoroEnd = "__builtin_coro_end";
- static constexpr const char *builtinCoroFree = "__builtin_coro_free";
-
/// Given a builtin id for a function like "__builtin_fabsf", return a
/// Function* for "fabsf".
cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 979aed513f595..ce1e442be40b7 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5167,6 +5167,48 @@ mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMCoroIntrinsicIsInRampOpLowering::matchAndRewrite(
+ cir::CoroIntrinsicIsInRampOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return mlir::failure();
+}
+
+mlir::LogicalResult CIRToLLVMCoroIntrinsicFreeOpLowering::matchAndRewrite(
+ cir::CoroIntrinsicFreeOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return mlir::failure();
+}
+
+mlir::LogicalResult CIRToLLVMCoroIntrinsicEndOpLowering::matchAndRewrite(
+ cir::CoroIntrinsicEndOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return mlir::failure();
+}
+
+mlir::LogicalResult CIRToLLVMCoroIntrinsicAllocOpLowering::matchAndRewrite(
+ cir::CoroIntrinsicAllocOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return mlir::failure();
+}
+
+mlir::LogicalResult CIRToLLVMCoroIntrinsicBeginOpLowering::matchAndRewrite(
+ cir::CoroIntrinsicBeginOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return mlir::failure();
+}
+
+mlir::LogicalResult CIRToLLVMCoroIntrinsicIdOpLowering::matchAndRewrite(
+ cir::CoroIntrinsicIdOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return mlir::failure();
+}
+
+mlir::LogicalResult CIRToLLVMCoroIntrinsicSizeOpLowering::matchAndRewrite(
+ cir::CoroIntrinsicSizeOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ return mlir::failure();
+}
+
mlir::LogicalResult CIRToLLVMCpuIdOpLowering::matchAndRewrite(
cir::CpuIdOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGen/coro-builtins-err.cpp b/clang/test/CIR/CodeGen/coro-builtins-err.cpp
new file mode 100644
index 0000000000000..ffbbd706b61bf
--- /dev/null
+++ b/clang/test/CIR/CodeGen/coro-builtins-err.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines -fclangir -emit-cir %s -o %t.cir -verify
+
+void a(void) {
+ __builtin_coro_alloc(); // expected-error {{this builtin expect that __builtin_coro_id has been used earlier in this function}}
+ __builtin_coro_begin(0); // expected-error {{this builtin expect that __builtin_coro_id has been used earlier in this function}}
+ __builtin_coro_free(0); // expected-error {{this builtin expect that __builtin_coro_id has been used earlier in this function}}
+
+ __builtin_coro_id(32, 0, 0, 0);
+ __builtin_coro_id(32, 0, 0, 0); // expected-error {{only one __builtin_coro_id}}
+}
diff --git a/clang/test/CIR/CodeGen/coro-builtins.cpp b/clang/test/CIR/CodeGen/coro-builtins.cpp
new file mode 100644
index 0000000000000..f92f4d996c460
--- /dev/null
+++ b/clang/test/CIR/CodeGen/coro-builtins.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+
+void *myAlloc(long long);
+
+// CIR: cir.func {{.*}} @_Z1fi
+void f(int n) {
+ int promise;
+ // CIR: %[[ADDR:.*]] = cir.alloca "n"
+ // CIR: %[[PROMISE:.*]] = cir.alloca "promise"
+
+ __builtin_coro_id(32, &promise, 0, 0);
+ // CIR: %[[CORO_ID_ALIGN:.*]] = cir.const #cir.int<32>
+ // CIR: %[[CAS_PROM:.*]] = cir.cast bitcast %[[PROMISE]]
+ // CIR: %[[COROID:.*]] = cir.coro.intrinsic.id(%[[CORO_ID_ALIGN]], %[[CAS_PROM]], {{.*}}, {{.*}})
+
+ __builtin_coro_alloc();
+ // CIR: cir.coro.intrinsic.alloc(%[[COROID]])
+
+ // TODO
+ //__builtin_coro_noop();
+
+ __builtin_coro_begin(myAlloc(__builtin_coro_size()));
+ // TODO(CIR): Support both variants of the coroutine size intrinsic, matching
+ // `llvm.coro.size.i32` and `llvm.coro.size.i64`.
+ // CIR: %[[SIZE:.*]] = cir.coro.intrinsic.size()
+ // CIR: %[[CAST_SIZE:.*]] = cir.cast integral %[[SIZE]] : !u64i -> !s64i
+ // CIR: %[[MEM:.*]] = cir.call @_Z7myAllocx(%[[CAST_SIZE]])
+ // CIR: %[[FRAME:.*]] = cir.coro.intrinsic.begin(%[[COROID]], %[[MEM]])
+
+ // TODO(CIR):
+ //__builtin_coro_resume(__builtin_coro_frame());
+
+ // TODO(CIR):
+ //__builtin_coro_destroy(__builtin_coro_frame());
+
+ // TODO(CIR):
+ //__builtin_coro_done(__builtin_coro_frame());
+
+ // TODO(CIR):
+ //__builtin_coro_promise(__builtin_coro_frame(), 48, 0);
+
+ __builtin_coro_free(__builtin_coro_frame());
+ // CIR: cir.coro.intrinsic.free(%[[COROID]], %[[FRAME]])
+
+ // TODO(CIR):
+ //__builtin_coro_end(__builtin_coro_frame(), 0);
+
+ // 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 afaf66b8a8d06..fb088d110d0d8 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-task.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-task.cpp
@@ -22,11 +22,6 @@
// CIR: module {{.*}} {
// CIR-NEXT: cir.global external @_ZN5folly4coro9co_invokeE = #cir.zero : !rec_folly3A3Acoro3A3Aco_invoke_fn
-// CIR: cir.func builtin private @__builtin_coro_id(!u32i, !cir.ptr<!void>, !cir.ptr<!void>, !cir.ptr<!void>) -> !u32i
-// CIR: cir.func builtin private @__builtin_coro_alloc(!u32i) -> !cir.bool
-// CIR: cir.func builtin private @__builtin_coro_size() -> !u64i
-// CIR: cir.func builtin private @__builtin_coro_begin(!u32i, !cir.ptr<!void>) -> !cir.ptr<!void>
-
using VoidTask = folly::coro::Task<void>;
VoidTask silly_task() {
@@ -49,22 +44,21 @@ VoidTask silly_task() {
// CIR: %[[NullPtr:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
// CIR: %[[Align:.*]] = cir.const #cir.int<16> : !u32i
-// CIR: %[[CoroId:.*]] = cir.call @__builtin_coro_id(%[[Align]], %[[NullPtr]], %[[NullPtr]], %[[NullPtr]])
-
+// CIR: %[[CoroId:.*]] = cir.coro.intrinsic.id(%[[Align]], %[[NullPtr]], %[[NullPtr]], %[[NullPtr]]) : (!u32i, !cir.ptr<!void>, !cir.ptr<!void>, !cir.ptr<!void>) -> !u32i
// OGCG: %[[CoroId:.*]] = call token @llvm.coro.id(i32 16, ptr %[[VoidPromisseAddr]], ptr null, ptr null)
// Perform allocation calling operator 'new' depending on __builtin_coro_alloc and
// call __builtin_coro_begin for the final coroutine frame address.
-// CIR: %[[ShouldAlloc:.*]] = cir.call @__builtin_coro_alloc(%[[CoroId]]) : (!u32i) -> !cir.bool
+// CIR: %[[ShouldAlloc:.*]] = cir.coro.intrinsic.alloc(%[[CoroId]]) : (!u32i) -> !cir.bool
// CIR: cir.store{{.*}} %[[NullPtr]], %[[SavedFrameAddr]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// CIR: cir.if %[[ShouldAlloc]] {
-// CIR: %[[CoroSize:.*]] = cir.call @__builtin_coro_size() : () -> (!u64i {llvm.noundef})
+// CIR: %[[CoroSize:.*]] = cir.coro.intrinsic.size() : () -> !u64i
// CIR: %[[AllocAddr:.*]] = cir.call @_Znwm(%[[CoroSize]]) {allocsize = array<i32: 0>} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
// CIR: cir.store{{.*}} %[[AllocAddr]], %[[SavedFrameAddr]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// CIR: }
// CIR: %[[Load0:.*]] = cir.load{{.*}} %[[SavedFrameAddr]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
-// CIR: %[[CoroFrameAddr:.*]] = cir.call @__builtin_coro_begin(%[[CoroId]], %[[Load0]])
+// CIR: %[[CoroFrameAddr:.*]] = cir.coro.intrinsic.begin(%[[CoroId]], %[[Load0]]) : (!u32i, !cir.ptr<!void>) -> !cir.ptr<!void>
// OGCG: %[[ShouldAlloc:.*]] = call i1 @llvm.coro.alloc(token %[[CoroId]])
// OGCG: br i1 %[[ShouldAlloc]], label %coro.alloc, label %coro.init
@@ -196,11 +190,11 @@ VoidTask silly_task() {
// The `if` ensures we only call delete on non-null.
// CIR: } cleanup normal {
-// CIR: %[[FreeMem:.*]] = cir.call @__builtin_coro_free(%[[CoroId]], %[[CoroFrameAddr]])
+// CIR: %[[FreeMem:.*]] = cir.coro.intrinsic.free(%[[CoroId]], %[[CoroFrameAddr]]) : (!u32i, !cir.ptr<!void>) -> !cir.ptr<!void>
// CIR: %[[NullPtr2:.*]] = cir.const #cir.ptr<null>
// CIR: %[[Cond:.*]] = cir.cmp ne %[[FreeMem]], %[[NullPtr2]]
// CIR: cir.if %[[Cond]] {
-// CIR: %[[Size:.*]] = cir.call @__builtin_coro_size()
+// CIR: %[[Size:.*]] = cir.coro.intrinsic.size()
// CIR: cir.call @_ZdlPvm(%[[FreeMem]], %[[Size]])
// CIR: }
// CIR: cir.yield
@@ -220,7 +214,7 @@ VoidTask silly_task() {
// CIR: %[[CoroEndArg0:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
// CIR: %[[CoroEndArg1:.*]] = cir.const #false
-// CIR: = cir.call @__builtin_coro_end(%[[CoroEndArg0]], %[[CoroEndArg1]])
+// CIR: = cir.coro.intrinsic.end(%[[CoroEndArg0]], %[[CoroEndArg1]]) : (!cir.ptr<!void>, !cir.bool) -> !cir.bool
// CIR: %[[Tmp1:.*]] = cir.load{{.*}} %[[VoidTaskAddr]]
// CIR: cir.return %[[Tmp1]]
@@ -408,7 +402,7 @@ folly::coro::Task<void> yield1() {
// CIR: cir.yield
// CIR: } cleanup normal {
// CIR: }
-// CIR: = cir.call @__builtin_coro_end(%{{.*}}, %{{.*}}){{.*}}
+// CIR: = cir.coro.intrinsic.end(%{{.*}}, %{{.*}})
// CIR: %[[RETLOAD:.*]] = cir.load{{.*}} %[[RETVAL]]
// CIR: cir.return %[[RETLOAD]]
// CIR: }
>From 0115a8b040d38d7cb37c2ea8a2554b4cb0e2bc1f Mon Sep 17 00:00:00 2001
From: Andres Salamanca <andrealebarbaritos at gmail.com>
Date: Sun, 26 Jul 2026 19:16:04 -0500
Subject: [PATCH 2/3] Address some review comments
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 22 ++++++++------------
clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp | 14 +++++++------
2 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e62bc98c4a341..3e0e145ba858d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4717,6 +4717,7 @@ class CIR_CoroIntrinsicOp<string mnem, dag ins, dag outs,
`(` operands `)` `:` functional-type(operands, results) attr-dict
}];
}
+
//===----------------------------------------------------------------------===//
// Coroutine intrinsic IdOp
//===----------------------------------------------------------------------===//
@@ -4758,11 +4759,12 @@ def CIR_CoroIntrinsicAllocOp : CIR_CoroIntrinsicOp<"alloc",
}];
}
-// TODO: Replace the `id` operand with MLIR's `token` type once it becomes
-// available. This operand corresponds to the token produced by `llvm.coro.id`.
//===----------------------------------------------------------------------===//
// Coroutine intrinsic BeginOp
//===----------------------------------------------------------------------===//
+
+// TODO: Replace the `id` operand with MLIR's `token` type once it becomes
+// available. This operand corresponds to the token produced by `llvm.coro.id`.
def CIR_CoroIntrinsicBeginOp : CIR_CoroIntrinsicOp<"begin",
(ins CIR_UInt32:$id, CIR_VoidPtrType:$coroframeAddr),
(outs CIR_VoidPtrType:$result)> {
@@ -4777,6 +4779,7 @@ def CIR_CoroIntrinsicBeginOp : CIR_CoroIntrinsicOp<"begin",
//===----------------------------------------------------------------------===//
// Coroutine intrinsic EndOp
//===----------------------------------------------------------------------===//
+
def CIR_CoroIntrinsicEndOp : CIR_CoroIntrinsicOp<"end",
(ins CIR_VoidPtrType:$handle, CIR_AnyBoolType:$unwind),
(outs CIR_AnyBoolType:$result)> {
@@ -4791,11 +4794,12 @@ def CIR_CoroIntrinsicEndOp : CIR_CoroIntrinsicOp<"end",
}];
}
-// TODO: Replace the `id` operand with MLIR's `token` type once it becomes
-// available. This operand corresponds to the token produced by `llvm.coro.id`.
//===----------------------------------------------------------------------===//
// Coroutine intrinsic FreeOp
//===----------------------------------------------------------------------===//
+
+// TODO: Replace the `id` operand with MLIR's `token` type once it becomes
+// available. This operand corresponds to the token produced by `llvm.coro.id`.
def CIR_CoroIntrinsicFreeOp : CIR_CoroIntrinsicOp<"free",
(ins CIR_AnyIntType:$id, CIR_VoidPtrType:$coroframe),
(outs CIR_VoidPtrType:$result)> {
@@ -4811,6 +4815,7 @@ def CIR_CoroIntrinsicFreeOp : CIR_CoroIntrinsicOp<"free",
//===----------------------------------------------------------------------===//
// Coroutine intrinsic SizeOp
//===----------------------------------------------------------------------===//
+
def CIR_CoroIntrinsicSizeOp : CIR_CoroIntrinsicOp<"size",
(ins), (outs CIR_UInt64:$result)> {
let summary = "Represents llvm.coro.size";
@@ -4819,15 +4824,6 @@ def CIR_CoroIntrinsicSizeOp : CIR_CoroIntrinsicOp<"size",
}];
}
-//===----------------------------------------------------------------------===//
-// Coroutine intrinsic IsInRampOp
-//===----------------------------------------------------------------------===//
-
-def CIR_CoroIntrinsicIsInRampOp : CIR_CoroIntrinsicOp<"is_in_ramp",
- (ins), (outs CIR_AnyBoolType:$result), [Pure]> {
- let summary = "";
-}
-
//===----------------------------------------------------------------------===//
// CopyOp
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 2aa199c347152..ed54661aa3ef7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -233,9 +233,9 @@ CIRGenFunction::emitCoroIDBuiltinCall(const CallExpr *e) {
mlir::Location loc = getLoc(e->getBeginLoc());
llvm::SmallVector<mlir::Value, 4> args;
- for (auto const *arg : e->arguments()) {
+ for (const Expr *arg : e->arguments())
args.push_back(emitScalarExpr(arg));
- }
+
auto coroId = cir::CoroIntrinsicIdOp::create(cgm.getBuilder(), loc, args);
createCoroData(*this, curCoro, coroId, e);
return coroId;
@@ -266,9 +266,9 @@ CIRGenFunction::emitCoroBeginBuiltinCall(const CallExpr *e) {
}
llvm::SmallVector<mlir::Value, 2> args;
args.push_back(curCoro.data->coroId.getResult());
- for (auto const *arg : e->arguments()) {
+ for (const Expr *arg : e->arguments())
args.push_back(emitScalarExpr(arg));
- }
+
auto coroBegin =
cir::CoroIntrinsicBeginOp::create(cgm.getBuilder(), loc, args);
curCoro.data->coroBegin = coroBegin;
@@ -286,17 +286,19 @@ CIRGenFunction::emitCoroEndBuiltinCall(mlir::Location loc,
cir::CoroIntrinsicFreeOp
CIRGenFunction::emitCoroFreeBuiltin(const CallExpr *e) {
mlir::Location loc = getLoc(e->getBeginLoc());
+
if (!curCoro.data || !curCoro.data->coroId) {
cgm.error(e->getBeginLoc(), "this builtin expect that __builtin_coro_id has"
" been used earlier in this function");
return {};
}
+
auto coroFree = cir::CoroIntrinsicFreeOp::create(
cgm.getBuilder(), loc,
mlir::ValueRange{curCoro.data->coroId.getResult(),
curCoro.data->coroBegin});
- if (curCoro.data)
- curCoro.data->lastCoroFree = coroFree;
+
+ curCoro.data->lastCoroFree = coroFree;
return coroFree;
}
>From e68bd7f774219140c5831519080359922e461bd4 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <andrealebarbaritos at gmail.com>
Date: Sun, 26 Jul 2026 21:40:42 -0500
Subject: [PATCH 3/3] Fix after rebase.
---
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 ------
1 file changed, 6 deletions(-)
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ce1e442be40b7..ce0cc08e30c17 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5167,12 +5167,6 @@ mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
return mlir::success();
}
-mlir::LogicalResult CIRToLLVMCoroIntrinsicIsInRampOpLowering::matchAndRewrite(
- cir::CoroIntrinsicIsInRampOp op, OpAdaptor adaptor,
- mlir::ConversionPatternRewriter &rewriter) const {
- return mlir::failure();
-}
-
mlir::LogicalResult CIRToLLVMCoroIntrinsicFreeOpLowering::matchAndRewrite(
cir::CoroIntrinsicFreeOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
More information about the cfe-commits
mailing list