Author: Andres-Salamanca
Date: 2026-10-23T15:55:15-05:00
New Revision: de93044a5f303a8eb847cfc1f97c490de7809189

URL: 
https://github.com/llvm/llvm-project/commit/de93044a5f303a8eb847cfc1f97c490de7809189
DIFF: 
https://github.com/llvm/llvm-project/commit/de93044a5f303a8eb847cfc1f97c490de7809189.diff

LOG: [CIR] Replace coroutine unit attrs on FuncOp with a CoroutineKind enum 
attr (#234817)

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`).

Added: 
    

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
    clang/lib/CIR/Dialect/IR/CIRDialect.cpp
    clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp

Removed: 
    


################################################################################
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();


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

Reply via email to