[clang] [CIR] Replace coroutine unit attrs on FuncOp with a CoroutineKind enum attr (PR #234817)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 22 19:14:16 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Andres-Salamanca
<details>
<summary>Changes</summary>
Follow-up to #<!-- -->203802. `cir.func` used two independent unit attributes, `coroutine` and`flattened_coroutine`, to track whether a function is a coroutine and whether its body has been flattened. Nothing prevented both from being set at once, and `FlattenCFG` had to clear one and set the other by hand. Replace them with a single optional `coroutine_kind` attribute backed by a new `CoroutineKind` enum (`coroutine`, `flattened_coroutine`).
---
Full diff: https://github.com/llvm/llvm-project/pull/234817.diff
5 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+30)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+1-2)
- (modified) clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp (+1-1)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+17-17)
- (modified) clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp (+1-2)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index b3cc021989fde..54158e5b77d84 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1852,6 +1852,36 @@ def CIR_FuncInfoAttr : AnyAttrOf<[
CIR_FuncIdentityAttr
], "function information attribute">;
+
+//===----------------------------------------------------------------------===//
+// CoroutineKindAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroutineKind : CIR_I32Enum<"CoroutineKind", "coroutine kind", [
+ I32EnumCase<"Coroutine", 0, "coroutine">,
+ I32EnumCase<"FlattenedCoroutine", 1, "flattened_coroutine">
+]>;
+
+def CIR_CoroutineKindAttr : CIR_EnumAttr<CIR_CoroutineKind, "coroutine_kind"> {
+ let description = [{
+ Marks a `cir.func` as a coroutine and records which form its body
+ is in. A function without this attribute is not a coroutine.
+
+ - `coroutine`: the body still holds the structured `cir.coroutine` op
+ (and its `cir.await` / `cir.co_return` children), as emitted by CIRGen.
+ - `flattened_coroutine`: FlattenCFG has inlined those regions into plain
+ blocks. The function no longer contains a `cir.coroutine` op, but is
+ still a coroutine for the purposes of LLVM lowering.
+
+ On `cir.func` it is printed as a bare keyword:
+
+ ```mlir
+ cir.func coroutine @f() { ... }
+ cir.func flattened_coroutine @f() { ... }
+ ```
+ }];
+}
+
//===----------------------------------------------------------------------===//
// BitFieldDeclAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 571231462236f..f22c15aea680a 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4386,8 +4386,7 @@ def CIR_FuncOp : CIR_Op<"func", [
>:$global_visibility,
TypeAttrOf<CIR_FuncType>:$function_type,
UnitAttr:$builtin,
- UnitAttr:$coroutine,
- UnitAttr:$flattened_coroutine,
+ OptionalAttr<CIR_CoroutineKindAttr>:$coroutine_kind,
OptionalAttr<CIR_InlineKindAttr>:$inline_kind,
UnitAttr:$lambda,
UnitAttr:$no_proto,
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 0122d8a377b39..538db6747cf0b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -340,7 +340,7 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
cir::ConstantOp nullPtrCst = builder.getNullPtr(voidPtrTy, openCurlyLoc);
auto fn = mlir::cast<cir::FuncOp>(curFn);
- fn.setCoroutine(true);
+ fn.setCoroutineKind(cir::CoroutineKind::Coroutine);
const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
unsigned newAlign = ti.getNewAlign() / ti.getCharWidth();
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 7dcd0e9fefe29..838ea1e953e9b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2923,9 +2923,7 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
mlir::Builder &builder = parser.getBuilder();
mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
- mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
- mlir::StringAttr flattenedCoroutineNameAttr =
- getFlattenedCoroutineAttrName(state.name);
+ mlir::StringAttr coroutineKindNameAttr = getCoroutineKindAttrName(state.name);
mlir::StringAttr inlineKindNameAttr = getInlineKindAttrName(state.name);
mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
@@ -2939,14 +2937,19 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
- if (::mlir::succeeded(
- parser.parseOptionalKeyword(coroutineNameAttr.strref())))
- state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
-
- if (::mlir::succeeded(
- parser.parseOptionalKeyword(flattenedCoroutineNameAttr.strref())))
- state.addAttribute(flattenedCoroutineNameAttr,
- parser.getBuilder().getUnitAttr());
+
+ // Parse optional coroutine kind attribute
+ {
+ static constexpr llvm::StringRef keywords[] = {"coroutine",
+ "flattened_coroutine"};
+ llvm::StringRef keyword;
+ if (parser.parseOptionalKeyword(&keyword, keywords).succeeded())
+ state.addAttribute(
+ coroutineKindNameAttr,
+ cir::CoroutineKindAttr::get(builder.getContext(),
+ *cir::symbolizeCoroutineKind(keyword)));
+ }
+
// Parse optional inline kind attribute
cir::InlineKindAttr inlineKindAttr;
if (failed(parseInlineKindAttr(parser, inlineKindAttr)))
@@ -3289,11 +3292,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
if (getBuiltin())
p << " builtin";
- if (getCoroutine())
- p << " coroutine";
-
- if (getFlattenedCoroutine())
- p << " flattened_coroutine";
+ if (std::optional<cir::CoroutineKind> coroKind = getCoroutineKind())
+ p << ' ' << cir::stringifyCoroutineKind(*coroKind);
printInlineKindAttr(p, getInlineKindAttr());
@@ -3392,7 +3392,7 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
mlir::LogicalResult cir::FuncOp::verify() {
- if (!isDeclaration() && getCoroutine()) {
+ if (!isDeclaration() && getCoroutineKind() == cir::CoroutineKind::Coroutine) {
int coroutineOpCount = 0;
this->walk([&](Operation *op) {
if (isa<CoroutineOp>(op)) {
diff --git a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
index 87115ff26ed59..0bcdb90571f27 100644
--- a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
@@ -2324,8 +2324,7 @@ class CIRCoroutineFlattening : public mlir::OpRewritePattern<cir::CoroutineOp> {
// The coroutine regions have been flattened, so the original coroutine
// attribute no longer verifies. Preserve the information that this function
// originated from a coroutine for LLVM lowering.
- func.setCoroutine(false);
- func.setFlattenedCoroutine(true);
+ func.setCoroutineKind(cir::CoroutineKind::FlattenedCoroutine);
rewriter.eraseOp(coroOp);
return mlir::success();
``````````
</details>
https://github.com/llvm/llvm-project/pull/234817
More information about the cfe-commits
mailing list