Author: Amr Hesham
Date: 2025-12-16T19:52:44+01:00
New Revision: 18b38cf546a2561057f4ac39175ee77f5e858ae7

URL: 
https://github.com/llvm/llvm-project/commit/18b38cf546a2561057f4ac39175ee77f5e858ae7
DIFF: 
https://github.com/llvm/llvm-project/commit/18b38cf546a2561057f4ac39175ee77f5e858ae7.diff

LOG: [CIR] Support Try catch with handler for specific type (#171042)

Add support for try-catch with a handler for a specific exception type

Issue https://github.com/llvm/llvm-project/issues/154992

Added: 
    

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/include/clang/CIR/MissingFeatures.h
    clang/lib/CIR/CodeGen/CIRGenCXXABI.h
    clang/lib/CIR/CodeGen/CIRGenException.cpp
    clang/lib/CIR/CodeGen/CIRGenFunction.h
    clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
    clang/test/CIR/CodeGen/try-catch-tmp.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 240459428b22c..0e91d008dc52d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3032,6 +3032,8 @@ def CIR_CallOp : CIR_CallOpBase<"call", 
[NoRegionArguments]> {
   let results = (outs Optional<CIR_AnyType>:$result);
   let arguments = commonArgs;
 
+  let skipDefaultBuilders = 1;
+
   let builders = [
     OpBuilder<(ins "mlir::SymbolRefAttr":$callee, "mlir::Type":$resType,
                    "mlir::ValueRange":$operands), [{

diff  --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index ad8c7ca7336e6..a5b04d305b3e7 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -263,6 +263,7 @@ struct MissingFeatures {
   static bool ehCleanupScope() { return false; }
   static bool ehCleanupScopeRequiresEHCleanup() { return false; }
   static bool ehCleanupBranchFixups() { return false; }
+  static bool ehScopeFilter() { return false; }
   static bool ehstackBranches() { return false; }
   static bool emitBranchThroughCleanup() { return false; }
   static bool emitCheckedInBoundsGEP() { return false; }
@@ -376,7 +377,6 @@ struct MissingFeatures {
   static bool tryOp() { return false; }
   static bool vecTernaryOp() { return false; }
   static bool zextOp() { return false; }
-  static bool catchParamOp() { return false; }
 
   // Future CIR attributes
   static bool optInfoAttr() { return false; }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h 
b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index b96d656b91e62..1d5fce3036bf4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -161,6 +161,9 @@ class CIRGenCXXABI {
   /// Loads the incoming C++ this pointer as it was passed by the caller.
   mlir::Value loadIncomingCXXThis(CIRGenFunction &cgf);
 
+  virtual CatchTypeInfo
+  getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
+                               QualType catchHandlerType) = 0;
   virtual CatchTypeInfo getCatchAllTypeInfo();
 
   /// Get the implicit (second) parameter that comes after the "this" pointer,

diff  --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp 
b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index 70812452ed999..b84b3a3c92015 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -244,6 +244,29 @@ void CIRGenFunction::emitAnyExprToExn(const Expr *e, 
Address addr) {
   assert(!cir::MissingFeatures::ehCleanupScope());
 }
 
+void CIRGenFunction::populateUnwindResumeBlock(bool isCleanup,
+                                               cir::TryOp tryOp) {
+  const EHPersonality &personality = EHPersonality::get(*this);
+  // This can always be a call because we necessarily didn't find
+  // anything on the EH stack which needs our help.
+  const char *rethrowName = personality.catchallRethrowFn;
+  if (rethrowName != nullptr && !isCleanup) {
+    cgm.errorNYI("populateUnwindResumeBlock CatchallRethrowFn");
+    return;
+  }
+
+  unsigned regionsNum = tryOp->getNumRegions();
+  mlir::Region *unwindRegion = &tryOp->getRegion(regionsNum - 1);
+  mlir::Block *unwindResumeBlock = &unwindRegion->front();
+  if (!unwindResumeBlock->empty())
+    return;
+
+  // Emit cir.resume into the unwind region last block
+  mlir::OpBuilder::InsertionGuard guard(builder);
+  builder.setInsertionPointToStart(unwindResumeBlock);
+  cir::ResumeOp::create(builder, tryOp.getLoc());
+}
+
 mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {
   if (s.getTryBlock()->body_empty())
     return mlir::LogicalResult::success();
@@ -344,21 +367,63 @@ CIRGenFunction::emitCXXTryStmtUnderScope(const CXXTryStmt 
&s) {
   return mlir::success();
 }
 
+/// 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: WasmPersonality");
+    return;
+  }
+
+  if (EHPersonality::get(cgf).usesFuncletPads()) {
+    cgf.cgm.errorNYI("emitCatchDispatchBlock: usesFuncletPads");
+    return;
+  }
+
+  assert(std::find_if(catchScope.begin(), catchScope.end(),
+                      [](const auto &handler) {
+                        return !handler.type.rtti && handler.type.flags != 0;
+                      }) == catchScope.end() &&
+         "catch handler without type value or with not supported flags");
+
+  // There was no catch all handler, populate th EH regions for the
+  // enclosing scope.
+  if (!std::prev(catchScope.end())->isCatchAll())
+    cgf.populateEHCatchRegions(catchScope.getEnclosingEHScope(), tryOp);
+}
+
 void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp,
                                      bool isFnTryBlock) {
   unsigned numHandlers = s.getNumHandlers();
   EHCatchScope *catchScope = ehStack.pushCatch(numHandlers);
   for (unsigned i = 0; i != numHandlers; ++i) {
     const CXXCatchStmt *catchStmt = s.getHandler(i);
+    mlir::Region *handler = &tryOp.getHandlerRegions()[i];
     if (catchStmt->getExceptionDecl()) {
-      cgm.errorNYI("enterCXXTryStmt: CatchStmt with ExceptionDecl");
-      return;
-    }
+      // FIXME: Dropping the reference type on the type into makes it
+      // impossible to correctly implement catch-by-reference
+      // semantics for pointers.  Unfortunately, this is what all
+      // existing compilers do, and it's not clear that the standard
+      // personality routine is capable of doing this right.  See C++ DR 388:
+      //   http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388
+      Qualifiers caughtTypeQuals;
+      QualType caughtType = cgm.getASTContext().getUnqualifiedArrayType(
+          catchStmt->getCaughtType().getNonReferenceType(), caughtTypeQuals);
+      if (caughtType->isObjCObjectPointerType()) {
+        cgm.errorNYI("enterCXXTryStmt: caughtType ObjCObjectPointerType");
+        return;
+      }
 
-    // No exception decl indicates '...', a catch-all.
-    mlir::Region *handler = &tryOp.getHandlerRegions()[i];
-    catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler,
-                           s.getHandler(i));
+      CatchTypeInfo typeInfo = cgm.getCXXABI().getAddrOfCXXCatchHandlerType(
+          getLoc(catchStmt->getSourceRange()), caughtType,
+          catchStmt->getCaughtType());
+      catchScope->setHandler(i, typeInfo, handler, catchStmt);
+    } else {
+      // No exception decl indicates '...', a catch-all.
+      catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler,
+                             s.getHandler(i));
+    }
 
     // Under async exceptions, catch(...) needs to catch HW exception too
     // Mark scope with SehTryBegin as a SEH __try scope
@@ -397,6 +462,9 @@ void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, 
bool isFnTryBlock) {
     return;
   }
 
+  // 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> handlers(catchScope.begin(),
@@ -442,9 +510,6 @@ void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, 
bool isFnTryBlock) {
         emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);
     assert(emitResult.succeeded() && "failed to emit catch handler block");
 
-    assert(!cir::MissingFeatures::catchParamOp());
-    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
@@ -501,7 +566,8 @@ void CIRGenFunction::populateCatchHandlers(cir::TryOp 
tryOp) {
   if (!handlerTypesAttr || handlerTypesAttr.empty()) {
     // Accumulate all the handlers in scope.
     bool hasCatchAll = false;
-    llvm::SmallVector<mlir::Attribute, 4> handlerAttrs;
+    llvm::SmallPtrSet<mlir::Attribute, 4> catchTypes;
+    llvm::SmallVector<mlir::Attribute> handlerAttrs;
     for (EHScopeStack::iterator i = ehStack.begin(), e = ehStack.end(); i != e;
          ++i) {
       switch (i->getKind()) {
@@ -534,20 +600,25 @@ void CIRGenFunction::populateCatchHandlers(cir::TryOp 
tryOp) {
           break;
         }
 
-        cgm.errorNYI("emitLandingPad: non catch-all");
-        return;
+        // Check whether we already have a handler for this type.
+        // If not, keep track to later add to catch op.
+        if (catchTypes.insert(handler.type.rtti).second)
+          handlerAttrs.push_back(handler.type.rtti);
       }
 
       if (hasCatchAll)
         break;
     }
 
-    if (hasCatchAll) {
+    if (hasCatchAll)
       handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));
-    } else {
-      cgm.errorNYI("emitLandingPad: non catch-all");
-      return;
-    }
+
+    assert(!cir::MissingFeatures::ehScopeFilter());
+
+    // If there's no catch_all, attach the unwind region. This needs to be the
+    // last region in the TryOp catch list.
+    if (!hasCatchAll)
+      handlerAttrs.push_back(cir::UnwindAttr::get(&getMLIRContext()));
 
     // Add final array of clauses into TryOp.
     tryOp.setHandlerTypesAttr(
@@ -571,6 +642,13 @@ void 
CIRGenFunction::populateEHCatchRegions(EHScopeStack::stable_iterator scope,
     return;
   }
 
+  // The dispatch block for the end of the scope chain is a block that
+  // just resumes unwinding.
+  if (scope == ehStack.stable_end()) {
+    populateUnwindResumeBlock(/*isCleanup=*/true, tryOp);
+    return;
+  }
+
   // Otherwise, we should look at the actual scope.
   EHScope &ehScope = *ehStack.find(scope);
   bool mayThrow = ehScope.mayThrow();
@@ -588,16 +666,19 @@ void 
CIRGenFunction::populateEHCatchRegions(EHScopeStack::stable_iterator scope,
   if (!mayThrow) {
     switch (ehScope.getKind()) {
     case EHScope::Catch: {
+      mayThrow = true;
+
       // 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;
+
+      // TODO(cir): In the incubator we create a new basic block with YieldOp
+      // inside the attached cleanup region, but this part will be redesigned
+      break;
     }
     case EHScope::Cleanup: {
       cgm.errorNYI("getEHDispatchBlock: mayThrow & cleanup");

diff  --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index a2023caf36d3b..aff36d255b33d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -974,6 +974,7 @@ class CIRGenFunction : public CIRGenTypeCache {
     return false;
   }
 
+  void populateUnwindResumeBlock(bool isCleanup, cir::TryOp tryOp);
   void populateEHCatchRegions(EHScopeStack::stable_iterator scope,
                               cir::TryOp tryOp);
 

diff  --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp 
b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 56a735e0410d7..0d0d6c34a255a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -121,6 +121,13 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
 
   mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
                                           QualType ty) override;
+  CatchTypeInfo
+  getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
+                               QualType catchHandlerType) override {
+    auto rtti = dyn_cast<cir::GlobalViewAttr>(getAddrOfRTTIDescriptor(loc, 
ty));
+    assert(rtti && "expected GlobalViewAttr");
+    return CatchTypeInfo{rtti, 0};
+  }
 
   bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
     return true;
@@ -2310,7 +2317,6 @@ struct CallEndCatch final : EHScopeStack::Cleanup {
 
 static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Type paramTy,
                                   bool endMightThrow) {
-
   auto catchParam = cir::CatchParamOp::create(
       cgf.getBuilder(), cgf.getBuilder().getUnknownLoc(), paramTy);
 
@@ -2321,6 +2327,56 @@ static mlir::Value callBeginCatch(CIRGenFunction &cgf, 
mlir::Type paramTy,
   return catchParam.getParam();
 }
 
+/// A "special initializer" callback for initializing a catch
+/// parameter during catch initialization.
+static void initCatchParam(CIRGenFunction &cgf, const VarDecl &catchParam,
+                           Address paramAddr, SourceLocation loc) {
+  CanQualType catchType =
+      cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
+  // If we're catching by reference, we can just cast the object
+  // pointer to the appropriate pointer.
+  if (isa<ReferenceType>(catchType)) {
+    cgf.cgm.errorNYI(loc, "initCatchParam: ReferenceType");
+    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()) {
+      cgf.cgm.errorNYI(loc, "initCatchParam: hasPointerRepresentation");
+      return;
+    }
+
+    mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
+    mlir::Value catchParam =
+        callBeginCatch(cgf, cgf.getBuilder().getPointerTo(cirCatchTy), false);
+    LValue srcLV = cgf.makeNaturalAlignAddrLValue(catchParam, catchType);
+    LValue destLV = cgf.makeAddrLValue(paramAddr, catchType);
+    switch (tek) {
+    case cir::TEK_Complex: {
+      cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Complex");
+      return;
+    }
+    case cir::TEK_Scalar: {
+      auto exnLoad = cgf.emitLoadOfScalar(srcLV, loc);
+      cgf.emitStoreOfScalar(exnLoad, destLV, /*isInit=*/true);
+      return;
+    }
+    case cir::TEK_Aggregate:
+      llvm_unreachable("evaluation kind filtered out!");
+    }
+
+    // Otherwise, it returns a pointer into the exception object.
+    llvm_unreachable("bad evaluation kind");
+  }
+
+  cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate");
+}
+
 /// Begins a catch statement by initializing the catch variable and
 /// calling __cxa_begin_catch.
 void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf,
@@ -2355,5 +2411,29 @@ void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction 
&cgf,
     return;
   }
 
-  cgf.cgm.errorNYI("emitBeginCatch: catch with exception decl");
+  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, *catchParam, var.getObjectAddress(cgf),
+                 catchStmt->getBeginLoc());
+  cgf.emitAutoVarCleanups(var);
 }

diff  --git a/clang/test/CIR/CodeGen/try-catch-tmp.cpp 
b/clang/test/CIR/CodeGen/try-catch-tmp.cpp
index baf5d102a8b74..78d8567e0760f 100644
--- a/clang/test/CIR/CodeGen/try-catch-tmp.cpp
+++ b/clang/test/CIR/CodeGen/try-catch-tmp.cpp
@@ -5,13 +5,14 @@
 
 int division();
 
-void calling_division_inside_try_block() {
+void call_function_inside_try_catch_all() {
   try {
     division();
   } catch (...) {
   }
 }
 
+// CIR: cir.func {{.*}} @_Z34call_function_inside_try_catch_allv() 
personality(@__gxx_personality_v0)
 // CIR: cir.scope {
 // CIR:   cir.try {
 // CIR:       %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> !s32i
@@ -22,6 +23,8 @@ void calling_division_inside_try_block() {
 // CIR:   }
 // CIR: }
 
+
+// OGCG: define {{.*}} void @_Z34call_function_inside_try_catch_allv() #0 
personality ptr @__gxx_personality_v0
 // OGCG:   %[[EXN_OBJ_ADDR:.*]] = alloca ptr, align 8
 // OGCG:   %[[EH_SELECTOR_ADDR:.*]] = alloca i32, align 4
 // OGCG:   %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
@@ -43,3 +46,124 @@ void calling_division_inside_try_block() {
 // OGCG:   br label %[[TRY_CONT]]
 // OGCG: [[TRY_CONT]]:
 // OGCG:   ret void
+
+void call_function_inside_try_catch_with_exception_type() {
+  try {
+    division();
+  } catch (int e) {
+  }
+}
+
+// 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() : () -> !s32i
+// CIR:     cir.yield
+// CIR:   } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] {
+// CIR:     %[[CATCH_PARAM:.*]] = cir.catch_param : !cir.ptr<!s32i>
+// CIR      %[[TMP_CATCH_PARAM:.*]] = cir.load {{.*}} %[[CATCH_PRAM]] : 
!cir.ptr<!s32i>, !s32i
+// CIR      cir.store {{.*}} %[[TMP_CATCH_PARAM]], %[[EXCEPTION_ADDR]] : 
!s32i, !cir.ptr<!s32i>
+// CIR:     cir.yield
+// CIR:   } unwind {
+// CIR:     cir.resume
+// CIR:   }
+// CIR: }
+
+// OGCG: define {{.*}} void 
@_Z50call_function_inside_try_catch_with_exception_typev() #0 personality ptr 
@__gxx_personality_v0
+// OGCG:   %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
+// OGCG:   %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[E_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 %[[E_ADDR]], align 4
+// OGCG:   call void @__cxa_end_catch()
+// OGCG:   br label %[[TRY_CONT:.*]]
+// OGCG: [[TRY_CONT]]:
+// OGCG:   ret void
+// 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]]
+
+void call_function_inside_try_catch_with_exception_type_and_catch_all() {
+  try {
+    division();
+  } catch (int e) {
+  } catch (...) {
+  }
+}
+
+// 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() : () -> !s32i
+// CIR:     cir.yield
+// CIR:   } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] {
+// CIR:     %[[CATCH_PARAM:.*]] = cir.catch_param : !cir.ptr<!s32i>
+// CIR      %[[TMP_CATCH_PARAM:.*]] = cir.load {{.*}} %[[CATCH_PRAM]] : 
!cir.ptr<!s32i>, !s32i
+// CIR      cir.store {{.*}} %[[TMP_CATCH_PARAM]], %[[EXCEPTION_ADDR]] : 
!s32i, !cir.ptr<!s32i>
+// CIR:     cir.yield
+// CIR:   } catch all {
+// CIR:     %[[CATCH_PARAM]] = cir.catch_param : !cir.ptr<!void>
+// CIR:     cir.yield
+// CIR:   }
+// CIR: }
+
+// OGCG: define {{.*}} void 
@_Z64call_function_inside_try_catch_with_exception_type_and_catch_allv() #0 
personality ptr @__gxx_personality_v0
+// OGCG:   %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
+// OGCG:   %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
+// OGCG:   %[[E_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 
%[[CATCH_ALL:.*]]
+// 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 %[[E_ADDR]], align 4
+// OGCG:   call void @__cxa_end_catch()
+// OGCG:   br label %[[TRY_CONT:.*]]
+// OGCG: [[TRY_CONT]]:
+// OGCG:   ret void
+// OGCG: [[CATCH_ALL]]:
+// OGCG:   %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG:   %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr 
%[[TMP_EXCEPTION]])
+// OGCG:   call void @__cxa_end_catch()
+// OGCG:   br label %[[TRY_CONT]]


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

Reply via email to