[clang] [CIR][WIP] Make BeginCatchOp target-independent (PR #190612)

Amr Hesham via cfe-commits cfe-commits at lists.llvm.org
Sun Apr 19 06:41:52 PDT 2026


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

>From b9a4188f364a19ad31ee2b504c8077e34ea6ceee Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sun, 12 Apr 2026 17:56:43 +0200
Subject: [PATCH] [CIR] Make BeginCatchOp target-independent

---
 clang/lib/CIR/CodeGen/CIRGenCXXABI.h          |   4 -
 clang/lib/CIR/CodeGen/CIRGenException.cpp     | 180 +++++++++-
 clang/lib/CIR/CodeGen/CIRGenFunction.h        |   2 +
 clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 239 -------------
 .../CIR/Dialect/Transforms/EHABILowering.cpp  |  50 ++-
 .../CodeGen/try-catch-all-with-cleanup.cpp    |   9 -
 clang/test/CIR/CodeGen/try-catch.cpp          | 336 +++++++++++++++---
 7 files changed, 510 insertions(+), 310 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index 614d62fda44a5..bb100f7afd929 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -134,10 +134,6 @@ class CIRGenCXXABI {
 
   virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) = 0;
 
-  virtual void emitBeginCatch(CIRGenFunction &cgf,
-                              const CXXCatchStmt *catchStmt,
-                              mlir::Value ehToken) = 0;
-
   virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
                                                   QualType ty) = 0;
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index c80f292553a1c..7dd2a8d59199e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -273,6 +273,184 @@ void CIRGenFunction::addCatchHandlerAttr(
   }
 }
 
+namespace {
+/// From traditional LLVM, useful info for LLVM lowering support:
+/// A cleanup to call __cxa_end_catch.  In many cases, the caught
+/// exception type lets us state definitively that the thrown exception
+/// type does not have a destructor.  In particular:
+///   - Catch-alls tell us nothing, so we have to conservatively
+///     assume that the thrown exception might have a destructor.
+///   - Catches by reference behave according to their base types.
+///   - Catches of non-record types will only trigger for exceptions
+///     of non-record types, which never have destructors.
+///   - Catches of record types can trigger for arbitrary subclasses
+///     of the caught type, so we have to assume the actual thrown
+///     exception type might have a throwing destructor, even if the
+///     caught type's destructor is trivial or nothrow.
+struct CallEndCatch final : EHScopeStack::Cleanup {
+  CallEndCatch(bool mightThrow, mlir::Value catchToken)
+      : mightThrow(mightThrow), catchToken(catchToken) {}
+  bool mightThrow;
+  mlir::Value catchToken;
+
+  void emit(CIRGenFunction &cgf, Flags flags) override {
+    // Traditional LLVM codegen would emit a call to __cxa_end_catch
+    // here. For CIR, just let it pass since the cleanup is going
+    // to be emitted on a later pass when lowering the catch region.
+    // CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM));
+    cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken);
+    cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc);
+  }
+};
+} // namespace
+
+static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken,
+                                  mlir::Type exnPtrTy, bool endMightThrow) {
+  auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext());
+  auto beginCatch = cir::BeginCatchOp::create(cgf.getBuilder(),
+                                              cgf.getBuilder().getUnknownLoc(),
+                                              catchTokenTy, exnPtrTy, ehToken);
+
+  cgf.ehStack.pushCleanup<CallEndCatch>(
+      NormalAndEHCleanup,
+      endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor,
+      beginCatch.getCatchToken());
+
+  return beginCatch.getExnPtr();
+}
+
+/// A "special initializer" callback for initializing a catch
+/// parameter during catch initialization.
+static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken,
+                           const VarDecl &catchParam, Address paramAddr,
+                           SourceLocation loc) {
+  CIRGenBuilderTy builder = cgf.getBuilder();
+  CanQualType catchType =
+      cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
+  mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
+  mlir::Type exnPtrTy = builder.getPointerTo(cirCatchTy);
+  CharUnits caughtExnAlignment = cgf.getPointerAlign();
+
+  // If we're catching by reference, we can just cast the object
+  // pointer to the appropriate pointer.
+  if (isa<ReferenceType>(catchType)) {
+    QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType();
+    // We have no way to tell the personality function that we're
+    // catching by reference, so if we're catching a pointer,
+    // __cxa_begin_catch will actually return that pointer by value.
+    if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) {
+      QualType pointeeType = pt->getPointeeType();
+      // When catching by reference, generally we should just ignore
+      // this by-value pointer and use the exception object instead.
+      if (!pointeeType->isRecordType()) {
+        cgf.cgm.errorNYI(loc,
+                         "initCatchParam: catching a pointer of non-record");
+        return;
+      }
+    }
+
+    bool endCatchMightThrow = caughtType->isRecordType();
+    mlir::Value exnPtr =
+        callBeginCatch(cgf, ehToken, exnPtrTy, endCatchMightThrow);
+    Address exnPtrAddr = Address(exnPtr, caughtExnAlignment);
+    cgf.setAddrOfLocalVar(&catchParam, exnPtrAddr);
+    return;
+  }
+
+  // Scalars and complexes.
+  cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
+  if (tek != cir::TEK_Aggregate) {
+    // Notes for LLVM lowering:
+    // If the catch type is a pointer type, __cxa_begin_catch returns
+    // the pointer by value.
+    if (catchType->hasPointerRepresentation()) {
+      switch (catchType.getQualifiers().getObjCLifetime()) {
+      case Qualifiers::OCL_Strong:
+        cgf.cgm.errorNYI(loc,
+                         "initCatchParam: PointerRepresentation OCL_Strong");
+        return;
+
+      case Qualifiers::OCL_ExplicitNone:
+      case Qualifiers::OCL_Autoreleasing:
+        cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation "
+                              "OCL_ExplicitNone & OCL_Autoreleasing");
+        return;
+
+      case Qualifiers::OCL_None:
+        break;
+
+      case Qualifiers::OCL_Weak:
+        cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation OCL_Weak");
+        return;
+      }
+    }
+
+    // Otherwise, it returns a pointer into the exception object.
+    mlir::Value exnPtr = callBeginCatch(cgf, ehToken, exnPtrTy,
+                                        /*endMightThrow=*/false);
+    Address exnPtrAddr = Address(exnPtr, caughtExnAlignment);
+    cgf.setAddrOfLocalVar(&catchParam, exnPtrAddr);
+    return;
+  }
+
+  assert(isa<RecordType>(catchType) && "unexpected catch type!");
+  auto *catchRD = catchType->getAsCXXRecordDecl();
+  caughtExnAlignment = cgf.cgm.getClassPointerAlignment(catchRD);
+
+  // Check for a copy expression.  If we don't have a copy expression,
+  // that means a trivial copy is okay.
+  const Expr *copyExpr = catchParam.getInit();
+  if (!copyExpr) {
+    mlir::Value exnPtr =
+        callBeginCatch(cgf, ehToken, exnPtrTy, /*endMightThrow=*/true);
+    Address exnPtrAddr = Address(exnPtr, caughtExnAlignment);
+    cgf.setAddrOfLocalVar(&catchParam, exnPtrAddr);
+    return;
+  }
+
+  cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate non-trivial copy");
+}
+
+/// Begins a catch statement by initializing the catch variable and
+/// calling __cxa_begin_catch.
+void CIRGenFunction::emitBeginCatch(const CXXCatchStmt *catchStmt,
+                                    mlir::Value ehToken) {
+  // We have to be very careful with the ordering of cleanups here:
+  //   C++ [except.throw]p4:
+  //     The destruction [of the exception temporary] occurs
+  //     immediately after the destruction of the object declared in
+  //     the exception-declaration in the handler.
+  //
+  // So the precise ordering is:
+  //   1.  Construct catch variable.
+  //   2.  __cxa_begin_catch
+  //   3.  Enter __cxa_end_catch cleanup
+  //   4.  Enter dtor cleanup
+  //
+  // We do this by using a slightly abnormal initialization process.
+  // Delegation sequence:
+  //   - ExitCXXTryStmt opens a RunCleanupsScope
+  //     - EmitAutoVarAlloca creates the variable and debug info
+  //       - InitCatchParam initializes the variable from the exception
+  //       - CallBeginCatch calls __cxa_begin_catch
+  //       - CallBeginCatch enters the __cxa_end_catch cleanup
+  //     - EmitAutoVarCleanups enters the variable destructor cleanup
+  //   - EmitCXXTryStmt emits the code for the catch body
+  //   - EmitCXXTryStmt close the RunCleanupsScope
+  VarDecl *catchParam = catchStmt->getExceptionDecl();
+  if (!catchParam) {
+    callBeginCatch(*this, ehToken, builder.getVoidPtrTy(),
+                   /*endMightThrow=*/true);
+    return;
+  }
+
+  // Emit the local. Make sure the alloca's superseed the current scope, since
+  // these are going to be consumed by `cir.catch`, which is not within the
+  // current scope.
+  initCatchParam(*this, ehToken, *catchParam, Address::invalid(),
+                 catchStmt->getBeginLoc());
+}
+
 mlir::LogicalResult
 CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s,
                                cxxTryBodyEmitter &bodyCallback) {
@@ -384,7 +562,7 @@ CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s,
     // Initialize the catch variable.
     // TODO(cir): Move this out of CXXABI.
     assert(!cir::MissingFeatures::currentFuncletPad());
-    cgm.getCXXABI().emitBeginCatch(*this, catchStmt, ehToken);
+    emitBeginCatch(catchStmt, ehToken);
 
     // Emit the PGO counter increment.
     assert(!cir::MissingFeatures::incrementProfileCounter());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 7cbea29a7c3f9..0e6b23e5c23e2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1785,6 +1785,8 @@ class CIRGenFunction : public CIRGenTypeCache {
     virtual ~cxxTryBodyEmitter() = default;
   };
 
+  void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken);
+
   mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s,
                                      cxxTryBodyEmitter &bodyCallback);
   mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index c398e6183d91c..26892db694f64 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -82,9 +82,6 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
   void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
   void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
 
-  void emitBeginCatch(CIRGenFunction &cgf, const CXXCatchStmt *catchStmt,
-                      mlir::Value ehToken) override;
-
   bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
                               CXXDtorType dt) const override {
     // Itanium does not emit any destructor variant as an inline thunk.
@@ -2490,242 +2487,6 @@ Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf,
   return Address(finalPtr, newPtr.getElementType(), finalAlignment);
 }
 
-namespace {
-/// From traditional LLVM, useful info for LLVM lowering support:
-/// A cleanup to call __cxa_end_catch.  In many cases, the caught
-/// exception type lets us state definitively that the thrown exception
-/// type does not have a destructor.  In particular:
-///   - Catch-alls tell us nothing, so we have to conservatively
-///     assume that the thrown exception might have a destructor.
-///   - Catches by reference behave according to their base types.
-///   - Catches of non-record types will only trigger for exceptions
-///     of non-record types, which never have destructors.
-///   - Catches of record types can trigger for arbitrary subclasses
-///     of the caught type, so we have to assume the actual thrown
-///     exception type might have a throwing destructor, even if the
-///     caught type's destructor is trivial or nothrow.
-struct CallEndCatch final : EHScopeStack::Cleanup {
-  CallEndCatch(bool mightThrow, mlir::Value catchToken)
-      : mightThrow(mightThrow), catchToken(catchToken) {}
-  bool mightThrow;
-  mlir::Value catchToken;
-
-  void emit(CIRGenFunction &cgf, Flags flags) override {
-    // Traditional LLVM codegen would emit a call to __cxa_end_catch
-    // here. For CIR, just let it pass since the cleanup is going
-    // to be emitted on a later pass when lowering the catch region.
-    // CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM));
-    cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken);
-    cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc);
-  }
-};
-} // namespace
-
-static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken,
-                                  mlir::Type exnPtrTy, bool endMightThrow) {
-  auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext());
-  auto beginCatch = cir::BeginCatchOp::create(cgf.getBuilder(),
-                                              cgf.getBuilder().getUnknownLoc(),
-                                              catchTokenTy, exnPtrTy, ehToken);
-
-  cgf.ehStack.pushCleanup<CallEndCatch>(
-      NormalAndEHCleanup,
-      endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor,
-      beginCatch.getCatchToken());
-
-  return beginCatch.getExnPtr();
-}
-
-/// A "special initializer" callback for initializing a catch
-/// parameter during catch initialization.
-static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken,
-                           const VarDecl &catchParam, Address paramAddr,
-                           SourceLocation loc) {
-  CanQualType catchType =
-      cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
-  mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
-
-  // If we're catching by reference, we can just cast the object
-  // pointer to the appropriate pointer.
-  if (isa<ReferenceType>(catchType)) {
-    QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType();
-    bool endCatchMightThrow = caughtType->isRecordType();
-
-    mlir::Value adjustedExn =
-        callBeginCatch(cgf, ehToken, cirCatchTy, endCatchMightThrow);
-
-    // We have no way to tell the personality function that we're
-    // catching by reference, so if we're catching a pointer,
-    // __cxa_begin_catch will actually return that pointer by value.
-    if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) {
-      QualType pointeeType = pt->getPointeeType();
-      // When catching by reference, generally we should just ignore
-      // this by-value pointer and use the exception object instead.
-      if (!pointeeType->isRecordType()) {
-        cgf.cgm.errorNYI(loc,
-                         "initCatchParam: catching a pointer of non-record");
-      } else {
-        // Pull the pointer for the reference type off.
-        mlir::Type ptrTy = cgf.convertTypeForMem(caughtType);
-
-        // Create the temporary and write the adjusted pointer into it.
-        Address exnPtrTmp = cgf.createTempAlloca(
-            ptrTy, cgf.getPointerAlign(), cgf.getLoc(loc), "exn.byref.tmp");
-        mlir::Value casted = cgf.getBuilder().createBitcast(adjustedExn, ptrTy);
-        cgf.getBuilder().createStore(cgf.getLoc(loc), casted, exnPtrTmp);
-
-        // Bind the reference to the temporary.
-        adjustedExn = exnPtrTmp.emitRawPointer();
-      }
-    }
-
-    mlir::Value exnCast =
-        cgf.getBuilder().createBitcast(adjustedExn, cirCatchTy);
-    cgf.getBuilder().createStore(cgf.getLoc(loc), exnCast, paramAddr);
-    return;
-  }
-
-  // Scalars and complexes.
-  cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
-  if (tek != cir::TEK_Aggregate) {
-    // Notes for LLVM lowering:
-    // If the catch type is a pointer type, __cxa_begin_catch returns
-    // the pointer by value.
-    if (catchType->hasPointerRepresentation()) {
-      mlir::Value catchParam =
-          callBeginCatch(cgf, ehToken, cirCatchTy, /*endMightThrow=*/false);
-      switch (catchType.getQualifiers().getObjCLifetime()) {
-      case Qualifiers::OCL_Strong:
-        cgf.cgm.errorNYI(loc,
-                         "initCatchParam: PointerRepresentation OCL_Strong");
-        return;
-
-      case Qualifiers::OCL_ExplicitNone:
-      case Qualifiers::OCL_Autoreleasing:
-        cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation "
-                              "OCL_ExplicitNone & OCL_Autoreleasing");
-        return;
-
-      case Qualifiers::OCL_None:
-        cgf.getBuilder().createStore(cgf.getLoc(loc), catchParam, paramAddr);
-        return;
-
-      case Qualifiers::OCL_Weak:
-        cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation OCL_Weak");
-        return;
-      }
-
-      llvm_unreachable("bad ownership qualifier!");
-    }
-
-    // Otherwise, it returns a pointer into the exception object.
-    mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
-    mlir::Value catchParam =
-        callBeginCatch(cgf, ehToken, cgf.getBuilder().getPointerTo(cirCatchTy),
-                       /*endMightThrow=*/false);
-    LValue srcLV = cgf.makeNaturalAlignAddrLValue(catchParam, catchType);
-    LValue destLV = cgf.makeAddrLValue(paramAddr, catchType);
-    switch (tek) {
-    case cir::TEK_Complex: {
-      mlir::Value load = cgf.emitLoadOfComplex(srcLV, loc);
-      cgf.emitStoreOfComplex(cgf.getLoc(loc), load, destLV, /*isInit=*/true);
-      return;
-    }
-    case cir::TEK_Scalar: {
-      mlir::Value exnLoad = cgf.emitLoadOfScalar(srcLV, loc);
-      cgf.emitStoreOfScalar(exnLoad, destLV, /*isInit=*/true);
-      return;
-    }
-    case cir::TEK_Aggregate:
-      llvm_unreachable("evaluation kind filtered out!");
-    }
-
-    llvm_unreachable("bad evaluation kind");
-  }
-
-  assert(isa<RecordType>(catchType) && "unexpected catch type!");
-  auto *catchRD = catchType->getAsCXXRecordDecl();
-  CharUnits caughtExnAlignment = cgf.cgm.getClassPointerAlignment(catchRD);
-
-  // Check for a copy expression.  If we don't have a copy expression,
-  // that means a trivial copy is okay.
-  const Expr *copyExpr = catchParam.getInit();
-  if (!copyExpr) {
-    mlir::Type cirCatchPtrTy = cgf.getBuilder().getPointerTo(cirCatchTy);
-    mlir::Value rawAdjustedExn =
-        callBeginCatch(cgf, ehToken, cirCatchPtrTy, /*endMightThrow=*/true);
-    Address adjustedExn(rawAdjustedExn, cirCatchTy, caughtExnAlignment);
-    LValue dest = cgf.makeAddrLValue(paramAddr, catchType);
-    LValue src = cgf.makeAddrLValue(adjustedExn, catchType);
-    cgf.emitAggregateCopy(dest, src, catchType, AggValueSlot::DoesNotOverlap);
-    return;
-  }
-
-  cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate non-trivial copy");
-}
-
-/// Begins a catch statement by initializing the catch variable and
-/// calling __cxa_begin_catch.
-void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf,
-                                         const CXXCatchStmt *catchStmt,
-                                         mlir::Value ehToken) {
-  // We have to be very careful with the ordering of cleanups here:
-  //   C++ [except.throw]p4:
-  //     The destruction [of the exception temporary] occurs
-  //     immediately after the destruction of the object declared in
-  //     the exception-declaration in the handler.
-  //
-  // So the precise ordering is:
-  //   1.  Construct catch variable.
-  //   2.  __cxa_begin_catch
-  //   3.  Enter __cxa_end_catch cleanup
-  //   4.  Enter dtor cleanup
-  //
-  // We do this by using a slightly abnormal initialization process.
-  // Delegation sequence:
-  //   - ExitCXXTryStmt opens a RunCleanupsScope
-  //     - EmitAutoVarAlloca creates the variable and debug info
-  //       - InitCatchParam initializes the variable from the exception
-  //       - CallBeginCatch calls __cxa_begin_catch
-  //       - CallBeginCatch enters the __cxa_end_catch cleanup
-  //     - EmitAutoVarCleanups enters the variable destructor cleanup
-  //   - EmitCXXTryStmt emits the code for the catch body
-  //   - EmitCXXTryStmt close the RunCleanupsScope
-
-  VarDecl *catchParam = catchStmt->getExceptionDecl();
-  if (!catchParam) {
-    callBeginCatch(cgf, ehToken, cgf.getBuilder().getVoidPtrTy(),
-                   /*endMightThrow=*/true);
-    return;
-  }
-
-  auto getCatchParamAllocaIP = [&]() {
-    cir::CIRBaseBuilderTy::InsertPoint currIns =
-        cgf.getBuilder().saveInsertionPoint();
-    mlir::Operation *currParent = currIns.getBlock()->getParentOp();
-
-    mlir::Block *insertBlock = nullptr;
-    if (auto scopeOp = currParent->getParentOfType<cir::ScopeOp>()) {
-      insertBlock = &scopeOp.getScopeRegion().getBlocks().back();
-    } else if (auto fnOp = currParent->getParentOfType<cir::FuncOp>()) {
-      insertBlock = &fnOp.getRegion().getBlocks().back();
-    } else {
-      llvm_unreachable("unknown outermost scope-like parent");
-    }
-    return cgf.getBuilder().getBestAllocaInsertPoint(insertBlock);
-  };
-
-  // Emit the local. Make sure the alloca's superseed the current scope, since
-  // these are going to be consumed by `cir.catch`, which is not within the
-  // current scope.
-
-  CIRGenFunction::AutoVarEmission var =
-      cgf.emitAutoVarAlloca(*catchParam, getCatchParamAllocaIP());
-  initCatchParam(cgf, ehToken, *catchParam, var.getObjectAddress(cgf),
-                 catchStmt->getBeginLoc());
-  cgf.emitAutoVarCleanups(var);
-}
-
 bool CIRGenItaniumCXXABI::hasAnyUnusedVirtualInlineFunction(
     const CXXRecordDecl *rd) const {
   const auto &vtableLayout = cgm.getItaniumVTableContext().getVTableLayout(rd);
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index abdc32951f857..e9b11595163b5 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -281,6 +281,47 @@ mlir::LogicalResult ItaniumEHLowering::lowerFunc(cir::FuncOp funcOp) {
   return mlir::success();
 }
 
+static mlir::Value initCatchParam(mlir::OpBuilder &builder,
+                                  cir::BeginCatchOp op,
+                                  mlir::Value beginCatchCall) {
+  mlir::Value result = beginCatchCall;
+  mlir::Type expectedPtrType = op.getExnPtr().getType();
+
+  auto exceptionType =
+      mlir::cast<cir::PointerType>(expectedPtrType).getPointee();
+
+  if (auto exnPointeeType = mlir::dyn_cast<cir::PointerType>(exceptionType)) {
+    if (auto exnPointeePtrType =
+            mlir::dyn_cast<cir::PointerType>(exnPointeeType.getPointee())) {
+      if (mlir::isa<cir::RecordType>(exnPointeePtrType.getPointee())) {
+        auto parentFunc = op->getParentOfType<cir::FuncOp>();
+        mlir::Block *entryBlock = &parentFunc.getRegion().front();
+
+        mlir::Value exnPtrTmp;
+        {
+          mlir::OpBuilder::InsertionGuard guard(builder);
+          builder.setInsertionPointToStart(entryBlock);
+          exnPtrTmp = cir::AllocaOp::create(
+              builder, op->getLoc(), expectedPtrType, exceptionType,
+              "exn.byref.tmp", builder.getI64IntegerAttr(8));
+        }
+
+        result = cir::CastOp::create(builder, op.getLoc(), exceptionType,
+                                     cir::CastKind::bitcast, result);
+
+        cir::StoreOp::create(builder, op.getLoc(), result, exnPtrTmp, {}, {},
+                             {}, {});
+        result = exnPtrTmp;
+      }
+    }
+  }
+
+  return result.getType() == expectedPtrType
+             ? result
+             : cir::CastOp::create(builder, op->getLoc(), expectedPtrType,
+                                   cir::CastKind::bitcast, result);
+}
+
 /// Lower all EH operations connected to a single cir.eh.initiate.
 ///
 /// The cir.eh.initiate is the root of a token graph. The token it produces
@@ -394,13 +435,8 @@ void ItaniumEHLowering::lowerEhInitiate(
         auto callOp = cir::CallOp::create(
             builder, op.getLoc(), mlir::FlatSymbolRefAttr::get(beginCatchFunc),
             u8PtrType, mlir::ValueRange{exnPtr});
-        mlir::Value castResult = callOp.getResult();
-        mlir::Type expectedPtrType = op.getExnPtr().getType();
-        if (castResult.getType() != expectedPtrType)
-          castResult =
-              cir::CastOp::create(builder, op.getLoc(), expectedPtrType,
-                                  cir::CastKind::bitcast, callOp.getResult());
-        op.getExnPtr().replaceAllUsesWith(castResult);
+        mlir::Value result = initCatchParam(builder, op, callOp.getResult());
+        op.getExnPtr().replaceAllUsesWith(result);
         op.erase();
       } else if (auto op = mlir::dyn_cast<cir::EhDispatchOp>(user)) {
         // Read catch types from the dispatch and set them on the inflight op.
diff --git a/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp b/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp
index 3827275bfc1be..5e1cc064e5ea5 100644
--- a/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp
+++ b/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp
@@ -149,7 +149,6 @@ void test_catch_all_and_specific_with_cleanup() {
 // CIR-LABEL: cir.func {{.*}} @_Z40test_catch_all_and_specific_with_cleanupv()
 // CIR:   cir.scope {
 // CIR:     %[[S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init]
-// CIR:     %[[E:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"]
 // CIR:     cir.try {
 // CIR:       cir.call @_ZN1SC1Ev(%[[S]])
 // CIR:       cir.cleanup.scope {
@@ -163,8 +162,6 @@ void test_catch_all_and_specific_with_cleanup() {
 // CIR:     } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
 // CIR:       %{{.*}}, %[[EXN:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
 // CIR:       cir.cleanup.scope {
-// CIR:         cir.load{{.*}} %[[EXN]] : !cir.ptr<!s32i>, !s32i
-// CIR:         cir.store{{.*}} %{{.*}}, %[[E]] : !s32i, !cir.ptr<!s32i>
 // CIR:         cir.yield
 // CIR:       } cleanup all {
 // CIR:         cir.end_catch %{{.*}} : !cir.catch_token
@@ -186,7 +183,6 @@ void test_catch_all_and_specific_with_cleanup() {
 // CIR-FLAT-LABEL: cir.func {{.*}} @_Z40test_catch_all_and_specific_with_cleanupv()
 //
 // CIR-FLAT:         %[[S:.*]] = cir.alloca !rec_S
-// CIR-FLAT:         %[[E:.*]] = cir.alloca !s32i
 //
 // Ctor may throw; unwinds directly to the dispatch (no cleanup needed yet).
 // CIR-FLAT:         cir.try_call @_ZN1SC1Ev(%[[S]]) ^[[AFTER_CTOR:bb[0-9]+]], ^[[CTOR_UNWIND:bb[0-9]+]]
@@ -227,8 +223,6 @@ void test_catch_all_and_specific_with_cleanup() {
 // Catch (int): bind e, end_catch, merge to return.
 // CIR-FLAT:       ^[[CATCH_INT]](%{{.*}}: !cir.eh_token):
 // CIR-FLAT:         %{{.*}}, %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
-// CIR-FLAT:         cir.load{{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
-// CIR-FLAT:         cir.store{{.*}} %{{.*}}, %[[E]] : !s32i, !cir.ptr<!s32i>
 // CIR-FLAT:         cir.end_catch %{{.*}} : !cir.catch_token
 // CIR-FLAT:         cir.br ^{{.*}}
 //
@@ -248,7 +242,6 @@ void test_catch_all_and_specific_with_cleanup() {
 // LLVM-LABEL: define {{.*}} void @_Z40test_catch_all_and_specific_with_cleanupv()
 // LLVM-SAME:    personality ptr @__gxx_personality_v0
 // LLVM:         %[[S:.*]] = alloca %struct.S
-// LLVM:         %[[E:.*]] = alloca i32
 // LLVM:         invoke void @_ZN1SC1Ev({{.*}}%[[S]])
 // LLVM:                 to label %[[AFTER_CTOR:.*]] unwind label %[[CTOR_LP:.*]]
 // LLVM:       [[AFTER_CTOR]]:
@@ -269,8 +262,6 @@ void test_catch_all_and_specific_with_cleanup() {
 // LLVM:         icmp eq i32 {{.*}}, {{.*}}
 // LLVM:       {{.*}}:
 // LLVM:         call ptr @__cxa_begin_catch
-// LLVM:         load i32, ptr {{.*}}
-// LLVM:         store i32 {{.*}}, ptr %[[E]]
 // LLVM:         call void @__cxa_end_catch()
 // LLVM:       {{.*}}:
 // LLVM:         call ptr @__cxa_begin_catch
diff --git a/clang/test/CIR/CodeGen/try-catch.cpp b/clang/test/CIR/CodeGen/try-catch.cpp
index fd8b9294c9f92..6c8942e4fab2c 100644
--- a/clang/test/CIR/CodeGen/try-catch.cpp
+++ b/clang/test/CIR/CodeGen/try-catch.cpp
@@ -127,6 +127,7 @@ void try_catch_with_alloca() {
   }
 }
 
+// CIR: cir.func {{.*}} @_Z21try_catch_with_allocav() personality(@__gxx_personality_v0)
 // CIR: cir.scope {
 // CIR:   %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a"]
 // CIR:   %[[B_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b"]
@@ -213,7 +214,7 @@ void call_function_inside_try_catch_all() {
 // CIR:       %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
 // CIR:       cir.cleanup.scope {
 // CIR:         cir.yield
-// CIR:       } cleanup {{.*}} {
+// CIR:       } cleanup all {
 // CIR:         cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
 // CIR:         cir.yield
 // CIR:       }
@@ -291,17 +292,14 @@ void call_function_inside_try_catch_with_exception_type() {
 
 // CIR: cir.func {{.*}} @_Z50call_function_inside_try_catch_with_exception_typev() personality(@__gxx_personality_v0)
 // CIR: cir.scope {
-// CIR:   %[[EXCEPTION_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv()
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
 // CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
 // CIR:     cir.cleanup.scope {
-// CIR:       %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
-// CIR:       cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i>
 // CIR:       cir.yield
-// CIR:     } cleanup {{.*}} {
+// CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
 // CIR:       cir.yield
 // CIR:     }
@@ -342,8 +340,6 @@ void call_function_inside_try_catch_with_exception_type() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   %[[LOAD:.*]] = load i32, ptr %[[TOKEN]], align 4
-// LLVM:   store i32 %[[LOAD]], ptr {{.*}}, align 4
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -409,14 +405,12 @@ void call_function_inside_try_catch_with_ref_exception_type() {
 
 // CIR: cir.func {{.*}} @_Z54call_function_inside_try_catch_with_ref_exception_typev() personality(@__gxx_personality_v0)
 // CIR: cir.scope {
-// CIR:   %[[EXCEPTION_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["ref", const]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv()
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
-// CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
+// CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!s32i>>)
 // CIR:     cir.cleanup.scope {
-// CIR:       cir.store {{.*}} %[[EXN_PTR]], %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
 // CIR:       cir.yield
 // CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -459,7 +453,6 @@ void call_function_inside_try_catch_with_ref_exception_type() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   store ptr %[[TOKEN]], ptr %{{.*}}, align 8
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -524,17 +517,14 @@ void call_function_inside_try_catch_with_complex_exception_type() {
 
 // CIR: cir.func {{.*}} @_Z58call_function_inside_try_catch_with_complex_exception_typev() personality(@__gxx_personality_v0)
 // CIR: cir.scope {
-// CIR:   %[[EXCEPTION_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["e"]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv()
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTICi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
 // CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.complex<!s32i>>)
 // CIR:     cir.cleanup.scope {
-// CIR:       %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
-// CIR:       cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
 // CIR:       cir.yield
-// CIR:     } cleanup {{.*}} {
+// CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
 // CIR:       cir.yield
 // CIR:     }
@@ -575,8 +565,6 @@ void call_function_inside_try_catch_with_complex_exception_type() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   %[[LOAD:.*]] = load { i32, i32 }, ptr %[[TOKEN]], align 4
-// LLVM:   store { i32, i32 } %[[LOAD]], ptr {{.*}}, align 4
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -648,16 +636,14 @@ void call_function_inside_try_catch_with_array_exception_type() {
 
 // CIR: cir.func {{.*}} @_Z56call_function_inside_try_catch_with_array_exception_typev() personality(@__gxx_personality_v0)
 // CIR: cir.scope {
-// CIR:   %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["e"]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv()
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTIPi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
-// CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
+// CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!s32i>>)
 // CIR:     cir.cleanup.scope {
-// CIR:       cir.store {{.*}} %[[EXN_PTR]], %[[E_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
 // CIR:       cir.yield
-// CIR:     } cleanup {{.*}} {
+// CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
 // CIR:       cir.yield
 // CIR:     }
@@ -698,7 +684,6 @@ void call_function_inside_try_catch_with_array_exception_type() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   store ptr %[[TOKEN]], ptr {{.*}}, align 8
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -764,17 +749,14 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() {
 
 // CIR: cir.func {{.*}} @_Z64call_function_inside_try_catch_with_exception_type_and_catch_allv() personality(@__gxx_personality_v0)
 // CIR: cir.scope {
-// CIR:   %[[EXCEPTION_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv()
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
 // CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
 // CIR:     cir.cleanup.scope {
-// CIR:       %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
-// CIR:       cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i>
 // CIR:       cir.yield
-// CIR:     } cleanup {{.*}} {
+// CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
 // CIR:       cir.yield
 // CIR:     }
@@ -783,7 +765,7 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() {
 // CIR:     %[[CATCH_TOKEN2:.*]], %{{.*}} = cir.begin_catch %[[EH_TOKEN2]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
 // CIR:     cir.cleanup.scope {
 // CIR:       cir.yield
-// CIR:     } cleanup {{.*}} {
+// CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN2]] : !cir.catch_token
 // CIR:       cir.yield
 // CIR:     }
@@ -822,8 +804,6 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   %[[LOAD:.*]] = load i32, ptr %[[TOKEN]], align 4
-// LLVM:   store i32 %[[LOAD]], ptr {{.*}}, align 4
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -1009,16 +989,14 @@ void call_function_inside_try_catch_with_aggregate_exception_type() {
 }
 
 
-// CIR: cir.func {{.*}} @_Z60call_function_inside_try_catch_with_aggregate_exception_typev(){{.*}} personality(@__gxx_personality_v0) {
+// CIR: cir.func {{.*}} @_Z60call_function_inside_try_catch_with_aggregate_exception_typev() personality(@__gxx_personality_v0)
 // CIR: cir.scope {
-// CIR:   %[[E_ADDR:.*]] = cir.alloca !rec_CustomError, !cir.ptr<!rec_CustomError>, ["e"]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTI11CustomError> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
 // CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!rec_CustomError>)
 // CIR:     cir.cleanup.scope {
-// CIR:       cir.copy %[[EXN_PTR]] to %[[E_ADDR]] : !cir.ptr<!rec_CustomError>
 // CIR:       cir.yield
 // CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -1061,7 +1039,6 @@ void call_function_inside_try_catch_with_aggregate_exception_type() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   call void @llvm.memcpy.p0.p0.i64(ptr %{{.*}}, ptr %[[TOKEN]], i64 4, i1 false)
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -1130,17 +1107,12 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() {
 }
 
 // CIR: cir.func {{.*}} @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev(){{.*}} personality(@__gxx_personality_v0) {
-// CIR:   %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>, ["ref_ptr", const]
-// CIR:   %[[EXN_BYREF_TMP:.*]] = cir.alloca !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>>, ["exn.byref.tmp"]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTIP6Record> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token {{.*}}) {
-// CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!rec_Record>>)
+// CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>)
 // CIR:     cir.cleanup.scope {
-// CIR:       %[[EXN_PTR_REC_PTR:.*]] = cir.cast bitcast %[[EXN_PTR]] : !cir.ptr<!cir.ptr<!rec_Record>> -> !cir.ptr<!rec_Record>
-// CIR:       cir.store {{.*}} %[[EXN_PTR_REC_PTR]], %[[EXN_BYREF_TMP]] : !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>>
-// CIR:       cir.store {{.*}} %[[EXN_BYREF_TMP]], %[[E_ADDR]] : !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>
 // CIR:       cir.yield
 // CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -1153,8 +1125,6 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() {
 // CIR: }
 
 // LLVM: define {{.*}} void @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev() {{.*}} personality ptr @__gxx_personality_v0
-// LLVM:   %[[E_ADDR:.*]] = alloca ptr
-// LLVM:   %[[EXN_BYREF_TMP:.*]] = alloca ptr
 // LLVM:   br label %[[TRY_SCOPE:.*]]
 // LLVM: [[TRY_SCOPE]]:
 // LLVM:   br label %[[TRY_BEGIN:.*]]
@@ -1185,8 +1155,6 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   store ptr %[[TOKEN]], ptr %[[EXN_BYREF_TMP]], align 8
-// LLVM:   store ptr %[[EXN_BYREF_TMP]], ptr %[[E_ADDR]], align 8
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -1253,15 +1221,12 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
 
 // CIR: cir.func {{.*}} @_Z61call_function_inside_try_catch_with_exception_member_ptr_typev(){{.*}} personality(@__gxx_personality_v0) {
 // CIR: cir.scope {
-// CIR:   %[[E_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["memberPtr"]
 // CIR:   cir.try {
 // CIR:     %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
 // CIR:     cir.yield
 // CIR:   } catch [type #cir.global_view<@_ZTIM6Recordi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}} {
 // CIR:     %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s64i>)
 // CIR:     cir.cleanup.scope {
-// CIR:       %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s64i>, !s64i
-// CIR:       cir.store {{.*}} %[[TMP]], %[[E_ADDR]] : !s64i, !cir.ptr<!s64i>
 // CIR:       cir.yield
 // CIR:     } cleanup all {
 // CIR:       cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -1293,8 +1258,8 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
 // LLVM:   %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
 // LLVM:   br label %[[DISPATCH:.*]]
 // LLVM: [[DISPATCH]]:
-// LLVM:   %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
-// LLVM:   %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH:.*]] ]
+// LLVM:   %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH]] ]
+// LLVM:   %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH]] ]
 // LLVM:   %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIM6Recordi)
 // LLVM:   %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
 // LLVM:   br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
@@ -1304,8 +1269,6 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
 // LLVM:   %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
 // LLVM:   br label %[[CATCH_BODY:.*]]
 // LLVM: [[CATCH_BODY]]:
-// LLVM:   %[[LOAD:.*]] = load i64, ptr %[[TOKEN]], align 8
-// LLVM:   store i64 %[[LOAD]], ptr {{.*}}, align 8
 // LLVM:   br label %[[END_CATCH:.*]]
 // LLVM: [[END_CATCH]]:
 // LLVM:   call void @__cxa_end_catch()
@@ -1362,3 +1325,276 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
 // OGCG:   %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1
 // OGCG:   resume { ptr, i32 } %[[EXCEPTION_INFO]]
 
+int init_catch_param_with_type_int() {
+  int rv = 0;
+  try {
+    division();
+  } catch (int x) {
+    rv = x;
+  }
+  return rv;
+}
+
+// CIR: cir.func {{.*}} @_Z30init_catch_param_with_type_intv() {{.*}} personality(@__gxx_personality_v0)
+// CIR:   %[[RET_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR:   %[[RV_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["rv", init]
+// CIR:   cir.scope {
+// CIR:     cir.try {
+// CIR:       %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
+// CIR:       cir.yield
+// CIR:     } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
+// CIR:       %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
+// CIR:       cir.cleanup.scope {
+// CIR:         %[[TMP_EXN:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
+// CIR:         cir.store {{.*}} %[[TMP_EXN]], %[[RV_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR:         cir.yield
+// CIR:       } cleanup all {
+// CIR:         cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
+// CIR:         cir.yield
+// CIR:       }
+// CIR:       cir.yield
+// CIR:     } unwind (%{{.*}}: !cir.eh_token {{.*}}) {
+// CIR:       cir.resume %{{.*}} : !cir.eh_token
+// CIR:     }
+// CIR:   }
+// CIR:   %[[TMP_RV:.*]] = cir.load {{.*}} %[[RV_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR:   cir.store %[[TMP_RV]], %[[RET_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR:   cir.return %[[TMP_RET]] : !s32i
+
+// LLVM: define {{.*}} i32 @_Z30init_catch_param_with_type_intv() {{.*}} personality ptr @__gxx_personality_v0
+// LLVM:   %[[RET_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM:   %[[RV_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM:   br label %[[TRY_SCOPE:.*]]
+// LLVM: [[TRY_SCOPE]]:
+// LLVM:   br label %[[TRY_BEGIN:.*]]
+// LLVM: [[TRY_BEGIN]]:
+// LLVM:   %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// LLVM:           to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
+// LLVM: [[INVOKE_CONT]]:
+// LLVM:   br label %[[TRY_CONT:.*]]
+// LLVM: [[LANDING_PAD]]:
+// LLVM:   %[[LP:.*]] = landingpad { ptr, i32 }
+// LLVM:           catch ptr @_ZTIi
+// LLVM:   %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
+// LLVM:   %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
+// LLVM:   br label %[[CATCH:.*]]
+// LLVM: [[CATCH]]:
+// LLVM:   %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM:   br label %[[DISPATCH:.*]]
+// LLVM: [[DISPATCH]]:
+// LLVM:   %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH]] ]
+// LLVM:   %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)
+// LLVM:   %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
+// LLVM:   br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
+// LLVM: [[BEGIN_CATCH]]:
+// LLVM:   %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[EXN_PTR:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
+// LLVM:   br label %[[CATCH_BODY:.*]]
+// LLVM: [[CATCH_BODY]]:
+// LLVM:   %[[TMP_EXN:.*]] = load i32, ptr %[[EXN_PTR]], align 8
+// LLVM:   store i32 %[[TMP_EXN]], ptr %[[RV_ADDR]], align 4
+// LLVM:   br label %[[END_CATCH:.*]]
+// LLVM: [[END_CATCH]]:
+// LLVM:   call void @__cxa_end_catch()
+// LLVM:   br label %[[END_DISPATCH:.*]]
+// LLVM: [[END_DISPATCH]]:
+// LLVM:   br label %[[END_TRY:.*]]
+// LLVM: [[END_TRY]]:
+// LLVM:   br label %[[TRY_CONT:.*]]
+// LLVM: [[RESUME]]:
+// LLVM:   %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0
+// LLVM:   %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1
+// LLVM:   resume { ptr, i32 } %[[EXCEPTION_INFO]]
+// LLVM: [[TRY_CONT]]:
+// LLVM:   br label %[[DONE:.*]]
+// LLVM: [[DONE]]:
+// LLVM:   %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// LLVM:   store i32 %[[TMP_RV]], ptr %[[RET_ADDR]], align 4
+// LLVM:   %[[TMP_RET:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM:   ret i32 %[[TMP_RET]]
+
+// OGCG: define {{.*}} i32 @_Z30init_catch_param_with_type_intv() {{.*}} personality ptr @__gxx_personality_v0
+// OGCG:   %[[RV_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
+// OGCG:   %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[X_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// OGCG:           to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]]
+// OGCG: [[INVOKE_NORMAL]]:
+// OGCG:   br label %[[TRY_CONT:.*]]
+// OGCG: [[INVOKE_UNWIND]]:
+// OGCG:   %[[LANDING_PAD:.*]] = landingpad { ptr, i32 }
+// OGCG:           catch ptr @_ZTIi
+// OGCG:   %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0
+// OGCG:   store ptr %[[EXCEPTION]], ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG:   %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1
+// OGCG:   store i32 %[[EH_TYPE_ID]], ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG:   br label %[[CATCH_DISPATCH]]
+// OGCG: [[CATCH_DISPATCH]]:
+// OGCG:   %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG:   %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)
+// OGCG:   %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[TMP_EH_TYPE_ID]], %[[EH_TYPE_ID]]
+// OGCG:   br i1 %[[TYPE_ID_EQ]], label %[[CATCH_EXCEPTION:.*]], label %[[EH_RESUME:.*]]
+// OGCG: [[CATCH_EXCEPTION]]:
+// OGCG:   %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG:   %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]])
+// OGCG:   %[[TMP_BEGIN_CATCH:.*]] = load i32, ptr %[[BEGIN_CATCH]], align 4
+// OGCG:   store i32 %[[TMP_BEGIN_CATCH]], ptr %[[X_ADDR]], align 4
+// OGCG:   %[[TMP_X:.*]] = load i32, ptr %[[X_ADDR]], align 4
+// OGCG:   store i32 %[[TMP_X]], ptr %[[RV_ADDR]], align 4
+// OGCG:   call void @__cxa_end_catch()
+// OGCG:   br label %[[TRY_CONT]]
+// OGCG: [[TRY_CONT]]:
+// OGCG:   %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// OGCG:   ret i32 %[[TMP_RV]]
+// OGCG: [[EH_RESUME]]:
+// OGCG:   %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG:   %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG:   %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[TMP_EXCEPTION]], 0
+// OGCG:   %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1
+// OGCG:   resume { ptr, i32 } %[[EXCEPTION_INFO]]
+
+
+int init_catch_param_with_type_int_ptr() {
+  int rv = 0;
+  try {
+    division();
+  } catch (int *x) {
+    rv = *x;
+  }
+  return rv;
+}
+
+// CIR: cir.func {{.*}} @_Z34init_catch_param_with_type_int_ptrv() {{.*}} personality(@__gxx_personality_v0)
+// CIR:   %[[RET_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR:   %[[RV_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["rv", init]
+// CIR:   cir.scope {
+// CIR:     cir.try {
+// CIR:       %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
+// CIR:       cir.yield
+// CIR:     } catch [type #cir.global_view<@_ZTIPi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
+// CIR:       %catch_token, %exn_ptr = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!s32i>>)
+// CIR:       cir.cleanup.scope {
+// CIR:         %[[DEREF_EXN_PTR:.*]] = cir.load deref {{.*}} %[[EXN_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR:         %[[EXN_PTR:.*]] = cir.load {{.*}} %[[DEREF_EXN_PTR]] : !cir.ptr<!s32i>, !s32i
+// CIR:         cir.store {{.*}} %[[EXN_PTR]], %[[RV_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR:         cir.yield
+// CIR:       } cleanup all {
+// CIR:         cir.end_catch %catch_token : !cir.catch_token
+// CIR:         cir.yield
+// CIR:       }
+// CIR:       cir.yield
+// CIR:     } unwind (%{{.*}}: !cir.eh_token {{.*}} {
+// CIR:       cir.resume %{{.*}} : !cir.eh_token
+// CIR:     }
+// CIR:   }
+// CIR:   %[[TMP_RV:.*]] = cir.load {{.*}} %[[RV_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR:   cir.store %[[TMP_RV]], %[[RET_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR:   cir.return %[[TMP_RET]] : !s32i
+
+// LLVM: define {{.*}} i32 @_Z34init_catch_param_with_type_int_ptrv() {{.*}} personality ptr @__gxx_personality_v0
+// LLVM:   %[[RET_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM:   %[[RV_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM:   br label %[[TRY_SCOPE:.*]]
+// LLVM: [[TRY_SCOPE]]:
+// LLVM:   br label %[[TRY_BEGIN:.*]]
+// LLVM: [[TRY_BEGIN]]:
+// LLVM:   %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// LLVM:           to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
+// LLVM: [[INVOKE_CONT]]:
+// LLVM:   br label %[[TRY_CONT:.*]]
+// LLVM: [[LANDING_PAD]]:
+// LLVM:   %[[LP:.*]] = landingpad { ptr, i32 }
+// LLVM:           catch ptr @_ZTIPi
+// LLVM:   %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
+// LLVM:   %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
+// LLVM:   br label %[[CATCH:.*]]
+// LLVM: [[CATCH]]:
+// LLVM:   %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM:   br label %[[DISPATCH:.*]]
+// LLVM: [[DISPATCH]]:
+// LLVM:   %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH]] ]
+// LLVM:   %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPi)
+// LLVM:   %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
+// LLVM:   br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
+// LLVM: [[BEGIN_CATCH]]:
+// LLVM:   %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[EXN_PTR:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
+// LLVM:   br label %[[CATCH_BODY:.*]]
+// LLVM: [[CATCH_BODY]]:
+// LLVM:   %[[DEREF_EXN_PTR:.*]] = load ptr, ptr %[[EXN_PTR]], align 8
+// LLVM:   %[[TMP_EXN:.*]] = load i32, ptr %[[DEREF_EXN_PTR]], align 4
+// LLVM:   store i32 %[[TMP_EXN]], ptr %[[RV_ADDR]], align 4
+// LLVM:   br label %[[END_CATCH:.*]]
+// LLVM: [[END_CATCH]]:
+// LLVM:   call void @__cxa_end_catch()
+// LLVM:   br label %[[END_DISPATCH:.*]]
+// LLVM: [[END_DISPATCH]]:
+// LLVM:   br label %[[END_TRY:.*]]
+// LLVM: [[END_TRY]]:
+// LLVM:   br label %[[TRY_CONT:.*]]
+// LLVM: [[RESUME]]:
+// LLVM:   %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM:   %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0
+// LLVM:   %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1
+// LLVM:   resume { ptr, i32 } %[[EXCEPTION_INFO]]
+// LLVM: [[TRY_CONT]]:
+// LLVM:   br label %[[DONE:.*]]
+// LLVM: [[DONE]]:
+// LLVM:   %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// LLVM:   store i32 %[[TMP_RV]], ptr %[[RET_ADDR]], align 4
+// LLVM:   %[[TMP_RET:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM:   ret i32 %[[TMP_RET]]
+
+
+// OGCG: define {{.*}} i32 @_Z34init_catch_param_with_type_int_ptrv() {{.*}} personality ptr @__gxx_personality_v0
+// OGCG:   %[[RV_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
+// OGCG:   %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[C_ADDR:.*]] = alloca ptr, align 8
+// OGCG:   %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// OGCG:           to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]]
+// OGCG: [[INVOKE_NORMAL]]:
+// OGCG:   br label %[[TRY_CONT:.*]]
+// OGCG: [[INVOKE_UNWIND]]:
+// OGCG:   %[[LANDING_PAD:.*]] = landingpad { ptr, i32 }
+// OGCG:           catch ptr @_ZTIPi
+// OGCG:   %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0
+// OGCG:   store ptr %[[EXCEPTION]], ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG:   %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1
+// OGCG:   store i32 %[[EH_TYPE_ID]], ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG:   br label %[[CATCH_DISPATCH]]
+// OGCG: [[CATCH_DISPATCH]]:
+// OGCG:   %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG:   %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPi)
+// OGCG:   %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[TMP_EH_TYPE_ID]], %[[EH_TYPE_ID]]
+// OGCG:   br i1 %[[TYPE_ID_EQ]], label %[[CATCH_EXCEPTION:.*]], label %[[EH_RESUME:.*]]
+// OGCG: [[CATCH_EXCEPTION]]:
+// OGCG:   %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG:   %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]])
+// OGCG:   store ptr %[[BEGIN_CATCH]], ptr %[[X_ADDR]], align 8
+// OGCG:   %[[DEREF_X:.*]] = load ptr, ptr %[[X_ADDR]], align 8
+// OGCG:   %[[TMP_X:.*]] = load i32, ptr %[[DEREF_X]], align 4
+// OGCG:   store i32 %[[TMP_X]], ptr %[[RV_ADDR]], align 4
+// OGCG:   call void @__cxa_end_catch()
+// OGCG:   br label %[[TRY_CONT]]
+// OGCG: [[TRY_CONT]]:
+// OGCG:   %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// OGCG:   ret i32 %[[TMP_RV]]
+// OGCG: [[EH_RESUME]]:
+// OGCG:   %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG:   %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG:   %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[TMP_EXCEPTION]], 0
+// OGCG:   %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1
+// OGCG:   resume { ptr, i32 } %[[EXCEPTION_INFO]]



More information about the cfe-commits mailing list