================
@@ -301,6 +303,53 @@ mlir::Block
*ItaniumEHLowering::buildTerminateBlock(cir::FuncOp funcOp,
return terminateBlock;
}
+/// Read-only walk of the eh_token graph from an initiate's root token,
+/// collecting every cir.eh.dispatch its exception can reach, innermost first.
+/// The token flows through cleanups to the innermost dispatch and then, via
+/// that dispatch's continue-unwind edge, on to each enclosing dispatch (nested
+/// try/catch). The walk follows the token into catch-handler blocks too, but
+/// it dead-ends there because cir.begin_catch consumes the eh_token (producing
+/// a catch_token), so only the unwind chain yields further dispatches.
+///
+/// This is computed before any destructive lowering so a landing pad's catch
+/// types -- which are a property of the EH graph -- do not depend on the order
+/// in which the destructive per-initiate traversal tears down shared
+/// token-graph edges. \p dispatches is left empty for a cleanup-only initiate
+/// that reaches no dispatch (e.g. a path that only resumes).
+static void
+collectReachableDispatches(mlir::Value rootToken,
+ llvm::SmallVectorImpl<cir::EhDispatchOp>
&dispatches,
+ bool &reachesCleanup) {
+ llvm::SmallVector<mlir::Value> worklist;
+ llvm::SmallPtrSet<mlir::Value, 8> visited;
+ worklist.push_back(rootToken);
+ // Breadth-first (process in insertion order) so dispatches are discovered
+ // innermost first, matching the order catch clauses must appear in the
+ // landing pad.
+ for (unsigned i = 0; i < worklist.size(); ++i) {
+ mlir::Value current = worklist[i];
+ if (!visited.insert(current).second)
+ continue;
+ for (mlir::OpOperand &use : current.getUses()) {
+ mlir::Operation *user = use.getOwner();
+ // A cleanup anywhere on the unwind path (this initiate's own cleanup or
+ // an enclosing scope's) means the landing pad must carry the cleanup
+ // clause so destructors still run when a foreign exception unwinds
+ // through this frame.
+ if (mlir::isa<cir::BeginCleanupOp>(user))
+ reachesCleanup = true;
+ if (auto dispatch = mlir::dyn_cast<cir::EhDispatchOp>(user))
+ if (!llvm::is_contained(dispatches, dispatch))
----------------
adams381 wrote:
Made `dispatches` a `SmallSetVector`; the `is_contained` check is gone.
https://github.com/llvm/llvm-project/pull/205638
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits