[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 19:20:08 PDT 2026
================
@@ -110,6 +109,66 @@ struct ParamReferenceReplacerRAII {
};
} // namespace
+namespace {
+// Make sure to call coro.delete on scope exit.
+struct CallCoroDelete final : public EHScopeStack::Cleanup {
+ Stmt *deallocate;
+
+ // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
+
+ // Note: That deallocation will be emitted twice: once for a normal exit and
+ // once for exceptional exit. This usage is safe because Deallocate does not
+ // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
+ // builds a single call to a deallocation function which is safe to emit
+ // multiple times.
+ void emit(CIRGenFunction &cgf, Flags) override {
+ // Remember the current point, as we are going to emit deallocation code
+ // first to get to coro.free instruction that is an argument to a delete
+ // call.
+
+ if (cgf.emitStmt(deallocate, /*useCurrentScope=*/true).failed()) {
+ cgf.cgm.error(deallocate->getBeginLoc(),
+ "failed to emit coroutine deallocation expression");
+ return;
+ }
+
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ mlir::Location loc = cgf.getLoc(deallocate->getSourceRange());
+ cir::CallOp coroFree = cgf.curCoro.data->lastCoroFree;
+
+ if (!coroFree) {
+ cgf.cgm.error(deallocate->getBeginLoc(),
+ "Deallocation expressoin does not refer to coro.free");
+ return;
+ }
+
+ builder.setInsertionPointAfter(coroFree);
+ cir::ConstantOp nullPtrCst = builder.getNullPtr(cgf.voidPtrTy, loc);
+ auto cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
+ coroFree.getResult(), nullPtrCst);
----------------
Andres-Salamanca wrote:
Done, I ended up using `createPtrIsNotNull` because we should not destroy the coroutine frame when `coro.free` returns a non-null pointer.
https://github.com/llvm/llvm-project/pull/189281
More information about the cfe-commits
mailing list