[clang] [CIR] Add coroutine cleanup handling and update co_return semantics (PR #189281)

via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 6 13:54:51 PDT 2026


================
@@ -4120,6 +4120,67 @@ def CIR_AwaitOp : CIR_Op<"await",[
 
   let hasVerifier = 1;
 }
+//===----------------------------------------------------------------------===//
+// CoroBody
+//===----------------------------------------------------------------------===//
+def CIR_CoroBodyOp : CIR_Op<"coro.body", [
+  DeclareOpInterfaceMethods<RegionBranchOpInterface, ["getSuccessorInputs"]>,
+  RecursivelySpeculatable, AutomaticAllocationScope, NoRegionArguments,
+  RecursiveMemoryEffects
+]> {
+  let summary = "Region containing the user-authored coroutine body";
+  let description = [{
+    The `cir.coro.body` operation models the region where the user-authored
+    coroutine code is emitted.
+
+    This operation serves as a structural boundary separating the coroutine
+    setup and teardown logic (e.g. initial suspend, final suspend, and cleanup)
+    from the user-provided statements inside the coroutine.
+
+    The body region contains the code corresponding to the original function
+    body, including `co_await` and `co_return` expressions. In particular,
+    `cir.co_return` operations inside this region mark coroutine exit points
+    and introduce structured control flow that transfers execution to the
+    final suspend point of the coroutine.
+  }];
+
+  let regions = (region AnyRegion:$bodyRegion);
+
+  let skipDefaultBuilders = 1;
+
+  let builders = [
+    OpBuilder<(ins "BuilderCallbackRef":$bodyBuilder)>
+  ];
+
+  let assemblyFormat = [{
+    $bodyRegion attr-dict
+  }];
+
+  let hasLLVMLowering = false;
+  let hasVerifier = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// CoReturnOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoReturnOp : CIR_Op<"co_return", [
+  NoMemoryEffect, Pure, Terminator
----------------
Andres-Salamanca wrote:

Regarding the `HasParent` trait, I didn’t use it intentionally because it only checks the direct parent of the op. In our case, that is too restrictive.

For example, in scenarios like:

```mlir
"cir.coro.body"() ({
  "cir.scope"() ({
    ...
    "cir.if"(%0) ({
      ...
      "cir.co_return"()
    }, {
    })
    "cir.yield"()
  })
...
})
```

Here, `cir.co_return` is inside the `cir.if`, so using `HasParent` would fail with:
`'cir.co_return' op expects parent op 'cir.coro.body'`.

That’s why I didn’t use `HasParent`. Instead, the verifier allows the operation to be nested, as you mentioned in this comment https://github.com/llvm/llvm-project/pull/189281#discussion_r3019122125.

https://github.com/llvm/llvm-project/pull/189281


More information about the cfe-commits mailing list