================
@@ -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

Reply via email to