https://github.com/AmrDeveloper updated 
https://github.com/llvm/llvm-project/pull/165158

>From c4ead2dc0edd6698a6a661133dc633bd3b6a771e Mon Sep 17 00:00:00 2001
From: Amr Hesham <[email protected]>
Date: Sat, 25 Oct 2025 21:17:00 +0200
Subject: [PATCH] [CIR] Upstream non-empty Try block with catch all

---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp      |  48 +++-
 clang/lib/CIR/CodeGen/CIRGenCleanup.cpp   |  10 +-
 clang/lib/CIR/CodeGen/CIRGenCleanup.h     |   7 +-
 clang/lib/CIR/CodeGen/CIRGenException.cpp | 304 +++++++++++++++++++++-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp  |  10 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h    |  17 +-
 clang/lib/CIR/CodeGen/EHScopeStack.h      |   2 +
 clang/test/CIR/CodeGen/try-catch-tmp.cpp  |  44 ++++
 8 files changed, 434 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/try-catch-tmp.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 50d4c035d30a1..ea44c65636c6c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -465,12 +465,48 @@ static cir::CIRCallOpInterface
 emitCallLikeOp(CIRGenFunction &cgf, mlir::Location callLoc,
                cir::FuncType indirectFuncTy, mlir::Value indirectFuncVal,
                cir::FuncOp directFuncOp,
-               const SmallVectorImpl<mlir::Value> &cirCallArgs,
+               const SmallVectorImpl<mlir::Value> &cirCallArgs, bool isInvoke,
                const mlir::NamedAttrList &attrs) {
   CIRGenBuilderTy &builder = cgf.getBuilder();
 
   assert(!cir::MissingFeatures::opCallSurroundingTry());
-  assert(!cir::MissingFeatures::invokeOp());
+
+  if (isInvoke) {
+    // This call can throw, few options:
+    //  - If this call does not have an associated cir.try, use the
+    //    one provided by InvokeDest,
+    //  - User written try/catch clauses require calls to handle
+    //    exceptions under cir.try.
+
+    // In OG, we build the landing pad for this scope. In CIR, we emit a
+    // synthetic cir.try because this didn't come from code generating from a
+    // try/catch in C++.
+    assert(cgf.curLexScope && "expected scope");
+    cir::TryOp tryOp = cgf.curLexScope->getClosestTryParent();
+    if (!tryOp) {
+      cgf.cgm.errorNYI(
+          "emitCallLikeOp: call does not have an associated cir.try");
+      return {};
+    }
+
+    if (tryOp.getSynthetic()) {
+      cgf.cgm.errorNYI("emitCallLikeOp: tryOp synthetic");
+      return {};
+    }
+
+    cir::CallOp callOpWithExceptions;
+    if (indirectFuncTy) {
+      cgf.cgm.errorNYI("emitCallLikeOp: indirect function type");
+      return {};
+    }
+
+    callOpWithExceptions =
+        builder.createTryCallOp(callLoc, directFuncOp, cirCallArgs);
+
+    (void)cgf.getInvokeDest(tryOp);
+
+    return callOpWithExceptions;
+  }
 
   assert(builder.getInsertionBlock() && "expected valid basic block");
 
@@ -628,10 +664,16 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
     indirectFuncVal = calleePtr->getResult(0);
   }
 
+  // TODO(cir): currentFunctionUsesSEHTry
+  // TODO(cir): check for MSVCXXPersonality
+  // TODO(cir): Create NoThrowAttr
+  bool cannotThrow = attrs.getNamed("nothrow").has_value();
+  bool isInvoke = !cannotThrow && isInvokeDest();
+
   mlir::Location callLoc = loc;
   cir::CIRCallOpInterface theCall =
       emitCallLikeOp(*this, loc, indirectFuncTy, indirectFuncVal, directFuncOp,
-                     cirCallArgs, attrs);
+                     cirCallArgs, isInvoke, attrs);
 
   if (callOp)
     *callOp = theCall;
diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp
index 437db306f3369..3550a78cc1816 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp
@@ -188,9 +188,17 @@ void EHScopeStack::popCleanup() {
   }
 }
 
+bool EHScopeStack::requiresLandingPad() const {
+  for (stable_iterator si = getInnermostEHScope(); si != stable_end();) {
+    // TODO(cir): Skip lifetime markers.
+    assert(!cir::MissingFeatures::emitLifetimeMarkers());
+    return true;
+  }
+  return false;
+}
+
 EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) {
   char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers));
-  assert(!cir::MissingFeatures::innermostEHScope());
   EHCatchScope *scope =
       new (buffer) EHCatchScope(numHandlers, innermostEHScope);
   innermostEHScope = stable_begin();
diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.h 
b/clang/lib/CIR/CodeGen/CIRGenCleanup.h
index a035d792ef6d1..4e4e913574991 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCleanup.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.h
@@ -38,6 +38,8 @@ class EHScope {
   };
   enum { NumCommonBits = 3 };
 
+  bool isScopeMayThrow;
+
 protected:
   class CatchBitFields {
     friend class EHCatchScope;
@@ -92,10 +94,11 @@ class EHScope {
     // Traditional LLVM codegen also checks for `!block->use_empty()`, but
     // in CIRGen the block content is not important, just used as a way to
     // signal `hasEHBranches`.
-    assert(!cir::MissingFeatures::ehstackBranches());
-    return false;
+    return isScopeMayThrow;
   }
 
+  void setMayThrow(bool mayThrow) { isScopeMayThrow = mayThrow; }
+
   EHScopeStack::stable_iterator getEnclosingEHScope() const {
     return enclosingEHScope;
   }
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp 
b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index 67f46ffde8fda..700e5e0c67c45 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -14,6 +14,7 @@
 #include "CIRGenFunction.h"
 
 #include "clang/AST/StmtVisitor.h"
+#include "llvm/Support/SaveAndRestore.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -354,6 +355,33 @@ void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, 
cir::TryOp tryOp,
   }
 }
 
+/// Emit the structure of the dispatch block for the given catch scope.
+/// It is an invariant that the dispatch block already exists.
+static void emitCatchDispatchBlock(CIRGenFunction &cgf,
+                                   EHCatchScope &catchScope, cir::TryOp tryOp) 
{
+  if (EHPersonality::get(cgf).isWasmPersonality()) {
+    cgf.cgm.errorNYI("emitCatchDispatchBlock: WASM personality");
+    return;
+  }
+
+  if (EHPersonality::get(cgf).usesFuncletPads()) {
+    cgf.cgm.errorNYI("emitCatchDispatchBlock: usesFuncletPads");
+    return;
+  }
+
+  assert(catchScope.mayThrow() &&
+         "Expected catchScope that may throw exception");
+
+  // If there's only a single catch-all, getEHDispatchBlock returned
+  // that catch-all as the dispatch block.
+  if (catchScope.getNumHandlers() == 1 &&
+      catchScope.getHandler(0).isCatchAll()) {
+    return;
+  }
+
+  cgf.cgm.errorNYI("emitCatchDispatchBlock: non-catch all handler");
+}
+
 void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock) {
   unsigned numHandlers = s.getNumHandlers();
   EHCatchScope &catchScope = cast<EHCatchScope>(*ehStack.begin());
@@ -382,5 +410,279 @@ void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, 
bool isFnTryBlock) {
     return;
   }
 
-  cgm.errorNYI("exitCXXTryStmt: Required catch");
+  // Emit the structure of the EH dispatch for this catch.
+  emitCatchDispatchBlock(*this, catchScope, tryOp);
+
+  // Copy the handler blocks off before we pop the EH stack.  Emitting
+  // the handlers might scribble on this memory.
+  SmallVector<EHCatchScope::Handler, 8> handlers(
+      catchScope.begin(), catchScope.begin() + numHandlers);
+
+  ehStack.popCatch();
+
+  // Determine if we need an implicit rethrow for all these catch handlers;
+  // see the comment below.
+  bool doImplicitRethrow =
+      isFnTryBlock && isa<CXXDestructorDecl, CXXConstructorDecl>(curCodeDecl);
+
+  // Wasm uses Windows-style EH instructions, but merges all catch clauses into
+  // one big catchpad. So we save the old funclet pad here before we traverse
+  // each catch handler.
+  if (EHPersonality::get(*this).isWasmPersonality()) {
+    cgm.errorNYI("exitCXXTryStmt: WASM personality");
+    return;
+  }
+
+  bool hasCatchAll = false;
+  for (unsigned i = numHandlers; i != 0; --i) {
+    hasCatchAll |= handlers[i - 1].isCatchAll();
+    mlir::Region *catchRegion = handlers[i - 1].region;
+
+    mlir::OpBuilder::InsertionGuard guard(builder);
+    builder.setInsertionPointToStart(&catchRegion->front());
+
+    const CXXCatchStmt *catchStmt = s.getHandler(i - 1);
+
+    // Enter a cleanup scope, including the catch variable and the
+    // end-catch.
+    RunCleanupsScope catchScope(*this);
+
+    // Initialize the catch variable and set up the cleanups.
+    // TODO: emitBeginCatch
+
+    // Emit the PGO counter increment.
+    assert(!cir::MissingFeatures::incrementProfileCounter());
+
+    // Perform the body of the catch.
+    mlir::LogicalResult emitResult =
+        emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);
+    assert(emitResult.succeeded() && "failed to emit catch handler block");
+
+    // TODO(cir): This yeild should replaced by CatchParamOp once it upstreamed
+    cir::YieldOp::create(builder, tryOp->getLoc());
+
+    // [except.handle]p11:
+    //   The currently handled exception is rethrown if control
+    //   reaches the end of a handler of the function-try-block of a
+    //   constructor or destructor.
+
+    // It is important that we only do this on fallthrough and not on
+    // return.  Note that it's illegal to put a return in a
+    // constructor function-try-block's catch handler (p14), so this
+    // really only applies to destructors.
+    if (doImplicitRethrow) {
+      cgm.errorNYI("exitCXXTryStmt: doImplicitRethrow");
+      return;
+    }
+
+    // Fall out through the catch cleanups.
+    catchScope.forceCleanup();
+  }
+
+  // Because in wasm we merge all catch clauses into one big catchpad, in case
+  // none of the types in catch handlers matches after we test against each of
+  // them, we should unwind to the next EH enclosing scope. We generate a call
+  // to rethrow function here to do that.
+  if (EHPersonality::get(*this).isWasmPersonality() && !hasCatchAll) {
+    cgm.errorNYI("exitCXXTryStmt: WASM personality without catch all");
+  }
+
+  assert(!cir::MissingFeatures::incrementProfileCounter());
+}
+
+mlir::Operation *CIRGenFunction::emitLandingPad(cir::TryOp tryOp) {
+  assert(ehStack.requiresLandingPad());
+  assert(!cgm.getLangOpts().IgnoreExceptions &&
+         "LandingPad should not be emitted when -fignore-exceptions are in "
+         "effect.");
+
+  EHScope &innermostEHScope = *ehStack.find(ehStack.getInnermostEHScope());
+  switch (innermostEHScope.getKind()) {
+  case EHScope::Terminate:
+    cgm.errorNYI("emitLandingPad: terminate");
+    return {};
+
+  case EHScope::Catch:
+  case EHScope::Cleanup:
+  case EHScope::Filter:
+    // CIR does not cache landing pads.
+    break;
+  }
+
+  // If there's an existing TryOp, it means we got a `cir.try` scope
+  // that leads to this "landing pad" creation site. Otherwise, exceptions
+  // are enabled but a throwing function is called anyways (common pattern
+  // with function local static initializers).
+  mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();
+  if (!handlerTypesAttr || handlerTypesAttr.empty()) {
+    // Accumulate all the handlers in scope.
+    bool hasCatchAll = false;
+    llvm::SmallVector<mlir::Attribute, 4> handlerAttrs;
+    for (EHScopeStack::iterator i = ehStack.begin(), e = ehStack.end(); i != e;
+         ++i) {
+      switch (i->getKind()) {
+      case EHScope::Cleanup: {
+        cgm.errorNYI("emitLandingPad: Cleanup");
+        return {};
+      }
+
+      case EHScope::Filter: {
+        cgm.errorNYI("emitLandingPad: Filter");
+        return {};
+      }
+
+      case EHScope::Terminate: {
+        cgm.errorNYI("emitLandingPad: Terminate");
+        return {};
+      }
+
+      case EHScope::Catch:
+        break;
+      }
+
+      EHCatchScope &catchScope = cast<EHCatchScope>(*i);
+      for (unsigned handlerIdx = 0, he = catchScope.getNumHandlers();
+           handlerIdx != he; ++handlerIdx) {
+        EHCatchScope::Handler handler = catchScope.getHandler(handlerIdx);
+        assert(handler.type.flags == 0 &&
+               "landingpads do not support catch handler flags");
+
+        // If this is a catch-all, register that and abort.
+        if (handler.isCatchAll()) {
+          assert(!hasCatchAll);
+          hasCatchAll = true;
+          goto done;
+        }
+
+        cgm.errorNYI("emitLandingPad: non catch-all");
+        return {};
+      }
+
+      goto done;
+    }
+
+  done:
+    if (hasCatchAll) {
+      handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));
+    } else {
+      cgm.errorNYI("emitLandingPad: non catch-all");
+      return {};
+    }
+
+    // Add final array of clauses into TryOp.
+    tryOp.setHandlerTypesAttr(
+        mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));
+  }
+
+  // In traditional LLVM codegen. this tells the backend how to generate the
+  // landing pad by generating a branch to the dispatch block. In CIR,
+  // getEHDispatchBlock is used to populate blocks for later filing during
+  // cleanup handling.
+  (void)getEHDispatchBlock(ehStack.getInnermostEHScope(), tryOp);
+
+  return tryOp;
+}
+
+// Differently from LLVM traditional codegen, there are no dispatch blocks
+// to look at given cir.try_call does not jump to blocks like invoke does.
+// However, we keep this around since other parts of CIRGen use
+// getCachedEHDispatchBlock to infer state.
+mlir::Block *
+CIRGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator scope,
+                                   cir::TryOp tryOp) {
+  if (EHPersonality::get(*this).usesFuncletPads()) {
+    cgm.errorNYI("getEHDispatchBlock: usesFuncletPads");
+    return {};
+  }
+
+  // Otherwise, we should look at the actual scope.
+  EHScope &ehScope = *ehStack.find(scope);
+  bool mayThrow = ehScope.mayThrow();
+
+  mlir::Block *originalBlock = nullptr;
+  if (mayThrow && tryOp) {
+    // If the dispatch is cached but comes from a different tryOp, make sure:
+    // - Populate current `tryOp` with a new dispatch block regardless.
+    // - Update the map to enqueue new dispatchBlock to also get a cleanup. See
+    // code at the end of the function.
+    cgm.errorNYI("getEHDispatchBlock: mayThrow & tryOp");
+    return {};
+  }
+
+  if (!mayThrow) {
+    switch (ehScope.getKind()) {
+    case EHScope::Catch: {
+      // LLVM does some optimization with branches here, CIR just keep track of
+      // the corresponding calls.
+      EHCatchScope &catchScope = cast<EHCatchScope>(ehScope);
+      if (catchScope.getNumHandlers() == 1 &&
+          catchScope.getHandler(0).isCatchAll()) {
+        mayThrow = true;
+        break;
+      }
+      cgm.errorNYI("getEHDispatchBlock: mayThrow non-catch all");
+      return {};
+    }
+    case EHScope::Cleanup: {
+      cgm.errorNYI("getEHDispatchBlock: mayThrow & cleanup");
+      return {};
+    }
+    case EHScope::Filter: {
+      cgm.errorNYI("getEHDispatchBlock: mayThrow & Filter");
+      return {};
+    }
+    case EHScope::Terminate: {
+      cgm.errorNYI("getEHDispatchBlock: mayThrow & Terminate");
+      return {};
+    }
+    }
+  }
+
+  if (originalBlock) {
+    cgm.errorNYI("getEHDispatchBlock: originalBlock");
+    return {};
+  }
+
+  ehScope.setMayThrow(mayThrow);
+  return {};
+}
+
+bool CIRGenFunction::isInvokeDest() {
+  if (!ehStack.requiresLandingPad())
+    return false;
+
+  // If exceptions are disabled/ignored and SEH is not in use, then there is no
+  // invoke destination. SEH "works" even if exceptions are off. In practice,
+  // this means that C++ destructors and other EH cleanups don't run, which is
+  // consistent with MSVC's behavior, except in the presence of -EHa
+  const LangOptions &lo = cgm.getLangOpts();
+  if (!lo.Exceptions || lo.IgnoreExceptions) {
+    cgm.errorNYI("isInvokeDest: no exceptions or ignore exception");
+    return false;
+  }
+
+  // CUDA device code doesn't have exceptions.
+  if (lo.CUDA && lo.CUDAIsDevice)
+    return false;
+
+  return true;
+}
+
+mlir::Operation *CIRGenFunction::getInvokeDestImpl(cir::TryOp tryOp) {
+  assert(ehStack.requiresLandingPad());
+  assert(!ehStack.empty());
+
+  // TODO(cir): add personality function
+
+  // CIR does not cache landing pads.
+  const EHPersonality &personality = EHPersonality::get(*this);
+
+  mlir::Operation *lp = nullptr;
+  if (personality.usesFuncletPads()) {
+    cgm.errorNYI("getInvokeDestImpl: usesFuncletPads");
+  } else {
+    lp = emitLandingPad(tryOp);
+  }
+
+  return lp;
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 5d5209b9ffb60..7422940fe4b2b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -412,6 +412,16 @@ void CIRGenFunction::LexicalScope::emitImplicitReturn() {
   (void)emitReturn(localScope->endLoc);
 }
 
+cir::TryOp CIRGenFunction::LexicalScope::getClosestTryParent() {
+  LexicalScope *scope = this;
+  while (scope) {
+    if (scope->isTry())
+      return scope->getTry();
+    scope = scope->parentScope;
+  }
+  return nullptr;
+}
+
 void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
                                    cir::FuncOp fn, cir::FuncType funcType,
                                    FunctionArgList args, SourceLocation loc,
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index e5cecaa573a6e..4d01f4adfa053 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -916,10 +916,23 @@ class CIRGenFunction : public CIRGenTypeCache {
     return false;
   }
 
+  mlir::Block *getEHDispatchBlock(EHScopeStack::stable_iterator scope,
+                                  cir::TryOp tryOp);
+
   /// The cleanup depth enclosing all the cleanups associated with the
   /// parameters.
   EHScopeStack::stable_iterator prologueCleanupDepth;
 
+  mlir::Operation *getInvokeDestImpl(cir::TryOp tryOp);
+  mlir::Operation *getInvokeDest(cir::TryOp tryOp) {
+    if (!ehStack.requiresLandingPad())
+      return nullptr;
+    // Return the respective cir.try, this can be used to compute
+    // any other relevant information.
+    return getInvokeDestImpl(tryOp);
+  }
+  bool isInvokeDest();
+
   /// Takes the old cleanup stack size and emits the cleanup blocks
   /// that have been added.
   void popCleanupBlocks(EHScopeStack::stable_iterator oldCleanupStackDepth);
@@ -1063,7 +1076,7 @@ class CIRGenFunction : public CIRGenTypeCache {
     bool isSwitch() { return scopeKind == Kind::Switch; }
     bool isTernary() { return scopeKind == Kind::Ternary; }
     bool isTry() { return scopeKind == Kind::Try; }
-
+    cir::TryOp getClosestTryParent();
     void setAsGlobalInit() { scopeKind = Kind::GlobalInit; }
     void setAsSwitch() { scopeKind = Kind::Switch; }
     void setAsTernary() { scopeKind = Kind::Ternary; }
@@ -1587,6 +1600,8 @@ class CIRGenFunction : public CIRGenTypeCache {
   void emitLambdaDelegatingInvokeBody(const CXXMethodDecl *md);
   void emitLambdaStaticInvokeBody(const CXXMethodDecl *md);
 
+  mlir::Operation *emitLandingPad(cir::TryOp tryOp);
+
   mlir::LogicalResult emitIfStmt(const clang::IfStmt &s);
 
   /// Emit code to compute the specified expression,
diff --git a/clang/lib/CIR/CodeGen/EHScopeStack.h 
b/clang/lib/CIR/CodeGen/EHScopeStack.h
index 9005b0106b2a4..699ef0b799c37 100644
--- a/clang/lib/CIR/CodeGen/EHScopeStack.h
+++ b/clang/lib/CIR/CodeGen/EHScopeStack.h
@@ -217,6 +217,8 @@ class EHScopeStack {
   /// Determines whether the exception-scopes stack is empty.
   bool empty() const { return startOfData == endOfBuffer; }
 
+  bool requiresLandingPad() const;
+
   /// Determines whether there are any normal cleanups on the stack.
   bool hasNormalCleanups() const {
     return innermostNormalCleanup != stable_end();
diff --git a/clang/test/CIR/CodeGen/try-catch-tmp.cpp 
b/clang/test/CIR/CodeGen/try-catch-tmp.cpp
new file mode 100644
index 0000000000000..078447f844d9a
--- /dev/null
+++ b/clang/test/CIR/CodeGen/try-catch-tmp.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-fcxx-exceptions -fexceptions -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+int division();
+
+void calling_division_inside_try_block() {
+  try {
+    division();
+  } catch (...) {
+  }
+}
+
+// CIR: cir.scope {
+// CIR:   cir.try {
+// CIR:       %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> !s32i
+// CIR:       cir.yield
+// CIR:   } catch all {
+// CIR:       cir.yield
+// CIR:   }
+// CIR: }
+
+// OGCG:   %[[EXN_OBJ_ADDR:.*]] = alloca ptr, align 8
+// OGCG:   %[[EH_SELECTOR_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// OGCG:           to label %[[INVOKE_CONT:.*]] unwind label 
%[[LANDING_PAD:.*]]
+// OGCG: [[INVOKE_CONT]]:
+// OGCG:   br label %[[TRY_CONT:.*]]
+// OGCG: [[LANDING_PAD]]:
+// OGCG:   %[[LP:.*]] = landingpad { ptr, i32 }
+// OGCG:           catch ptr null
+// OGCG:   %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
+// OGCG:   store ptr %[[EXN_OBJ]], ptr %[[EXN_OBJ_ADDR]], align 8
+// OGCG:   %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
+// OGCG:   store i32 %[[EH_SELECTOR_VAL]], ptr %[[EH_SELECTOR_ADDR]], align 4
+// OGCG:   br label %[[CATCH:.*]]
+// OGCG: [[CATCH]]:
+// OGCG:   %[[EXN_OBJ:.*]] = load ptr, ptr %[[EXN_OBJ_ADDR]], align 8
+// OGCG:   %[[CATCH_BEGIN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ]])
+// OGCG:   call void @__cxa_end_catch()
+// OGCG:   br label %[[TRY_CONT]]
+// OGCG: [[TRY_CONT]]:
+// OGCG:   ret void

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

Reply via email to