Skip to content

[CIR] Support reference type of non-record ptr in InitCatchParam - #195722

Merged
AmrDeveloper merged 3 commits into
llvm:mainfrom
AmrDeveloper:cir_catch_param_ref_non_record
May 17, 2026
Merged

[CIR] Support reference type of non-record ptr in InitCatchParam#195722
AmrDeveloper merged 3 commits into
llvm:mainfrom
AmrDeveloper:cir_catch_param_ref_non_record

Conversation

@AmrDeveloper

Copy link
Copy Markdown
Member

Support init reference type of non-record ptr type in InitCatchParam

@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels May 4, 2026
@llvmorg-github-actions

llvmorg-github-actions Bot commented May 4, 2026

Copy link
Copy Markdown

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

Changes

Support init reference type of non-record ptr type in InitCatchParam


Full diff: https://github.com/llvm/llvm-project/pull/195722.diff

6 Files Affected:

  • (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+1-1)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td (+11)
  • (modified) clang/include/clang/CIR/MissingFeatures.h (+1)
  • (modified) clang/lib/CIR/CodeGen/CIRGenException.cpp (+7-1)
  • (modified) clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp (+24-14)
  • (modified) clang/test/CIR/CodeGen/try-catch.cpp (+147-1)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 97d623ba5e6d9..98b631a8ad6ee 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -7691,7 +7691,7 @@ def CIR_InitCatchParamOp : CIR_Op<"init_catch_param"> {
   }];
 
   let arguments = (ins
-      CIR_PointerType:$exn_ptr,
+      CIR_AnyPtrOrEHTokenType:$exn_ptr,
       CIR_PointerType:$param_addr,
       CIR_InitCatchKind:$kind
   );
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index 3cc79b9796e06..11b6ff5f11d62 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -400,4 +400,15 @@ def CIR_ComparableType
   let cppFunctionName = "isComparableType";
 }
 
+//===----------------------------------------------------------------------===//
+// Exception handling token Type predicates
+//===----------------------------------------------------------------------===//
+
+def CIR_AnyEhTokenType : CIR_TypeBase<"::cir::EhTokenType", "EH Token type">;
+
+def CIR_AnyPtrOrEHTokenType
+    : AnyTypeOf<[CIR_AnyPtrType, CIR_AnyEhTokenType],
+                "any ptr or EH token type"> {
+}
+
 #endif // CLANG_CIR_DIALECT_IR_CIRTYPECONSTRAINTS_TD
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 645fae3e4404d..f1d3c33aae32c 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -370,6 +370,7 @@ struct MissingFeatures {
 
   // Maybe only needed for Windows exception handling
   static bool currentFuncletPad() { return false; }
+  static bool sizeOfUnwindException() { return false; }
 };
 
 } // namespace cir
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index 3c956801f6b52..d84c6090bd49a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -306,10 +306,15 @@ static void initCatchParam(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
   CanQualType catchType =
       cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
   cir::InitCatchKind kind;
+  bool shouldInitFromExnDirectly = false;
 
   // 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();
+    if (const PointerType *ptr = dyn_cast<PointerType>(caughtType)) {
+      shouldInitFromExnDirectly = !ptr->getPointeeType()->isRecordType();
+    }
     kind = cir::InitCatchKind::Reference;
   } else {
     cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
@@ -341,7 +346,8 @@ static void initCatchParam(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
 
   mlir::Value exnPtr = callBeginCatch(cgf, ehToken, builder.getVoidPtrTy());
   CIRGenFunction::AutoVarEmission var = cgf.emitAutoVarAlloca(catchParam);
-  cir::InitCatchParamOp::create(builder, cgf.getLoc(loc), exnPtr,
+  mlir::Value initExnSrc = shouldInitFromExnDirectly ? ehToken : exnPtr;
+  cir::InitCatchParamOp::create(builder, cgf.getLoc(loc), initExnSrc,
                                 var.getAllocatedAddress().getPointer(), kind);
   cgf.emitAutoVarCleanups(var);
 }
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index baec91de9f89c..84f495c568d3d 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -130,7 +130,7 @@ class ItaniumEHLowering : public EHABILowering {
   void lowerDispatch(cir::EhDispatchOp dispatch, mlir::Value exnPtr,
                      mlir::Value typeId,
                      SmallVectorImpl<mlir::Operation *> &deadOps);
-  void lowerInitCatchParam(cir::InitCatchParamOp op);
+  void lowerInitCatchParam(cir::InitCatchParamOp op, EhTokenMap &ehTokenMap);
 };
 
 /// Lower all EH operations in the module to the Itanium-specific form.
@@ -265,6 +265,14 @@ mlir::LogicalResult ItaniumEHLowering::lowerFunc(cir::FuncOp funcOp) {
   for (cir::EhInitiateOp initiateOp : initiateOps)
     lowerEhInitiate(initiateOp, ehTokenMap, deadOps);
 
+  // Lower any cir.init_catch_param ops in this function. These materialize
+  // the catch parameter local from the (already lowered) begin_catch result,
+  // and are independent of the eh_token graph traversal above.
+  SmallVector<cir::InitCatchParamOp> initCatchOps;
+  funcOp.walk([&](cir::InitCatchParamOp op) { initCatchOps.push_back(op); });
+  for (cir::InitCatchParamOp op : initCatchOps)
+    lowerInitCatchParam(op, ehTokenMap);
+
   // Erase operations that were deferred during per-initiate processing
   // (dispatch ops whose catch types were read by multiple initiates).
   for (mlir::Operation *op : deadOps)
@@ -279,14 +287,6 @@ mlir::LogicalResult ItaniumEHLowering::lowerFunc(cir::FuncOp funcOp) {
     }
   }
 
-  // Lower any cir.init_catch_param ops in this function. These materialize
-  // the catch parameter local from the (already lowered) begin_catch result,
-  // and are independent of the eh_token graph traversal above.
-  SmallVector<cir::InitCatchParamOp> initCatchOps;
-  funcOp.walk([&](cir::InitCatchParamOp op) { initCatchOps.push_back(op); });
-  for (cir::InitCatchParamOp op : initCatchOps)
-    lowerInitCatchParam(op);
-
   return mlir::success();
 }
 
@@ -557,7 +557,8 @@ void ItaniumEHLowering::lowerDispatch(
 ///   - NonTrivialCopy: copy the exception
 ///     object's bytes into the alloca via copy constructor.
 ///
-void ItaniumEHLowering::lowerInitCatchParam(cir::InitCatchParamOp op) {
+void ItaniumEHLowering::lowerInitCatchParam(cir::InitCatchParamOp op,
+                                            EhTokenMap &ehTokenMap) {
   builder.setInsertionPoint(op);
   mlir::Location loc = op.getLoc();
   mlir::Value exnPtr = op.getExnPtr();
@@ -574,10 +575,19 @@ void ItaniumEHLowering::lowerInitCatchParam(cir::InitCatchParamOp op) {
     if (const auto ref = mlir::dyn_cast<cir::PointerType>(elementType)) {
       // When catching by reference, generally we should just ignore
       // this by-value pointer and use the exception object instead.
-      if (auto ptr = mlir::dyn_cast<cir::PointerType>(ref.getPointee()))
-        if (!mlir::isa<cir::RecordType>(ptr.getPointee()))
-          llvm_unreachable(
-              "InitCatchParam: reference of pointer or non-record is NYI");
+      if (auto ptr = mlir::dyn_cast<cir::PointerType>(ref.getPointee())) {
+        if (!mlir::isa<cir::RecordType>(ptr.getPointee())) {
+          auto [exn, typeId] = ehTokenMap.lookup(exnPtr);
+
+          constexpr unsigned headerSize = 32;
+          assert(!MissingFeatures::sizeOfUnwindException());
+
+          auto index = cir::ConstantOp::create(
+              builder, loc, cir::IntAttr::get(u32Type, headerSize));
+          exnPtr =
+              cir::PtrStrideOp::create(builder, loc, exn.getType(), exn, index);
+        }
+      }
     }
 
     mlir::Value casted = cir::CastOp::create(builder, loc, elementType,
diff --git a/clang/test/CIR/CodeGen/try-catch.cpp b/clang/test/CIR/CodeGen/try-catch.cpp
index dd9ed9d97b795..c6a191792591f 100644
--- a/clang/test/CIR/CodeGen/try-catch.cpp
+++ b/clang/test/CIR/CodeGen/try-catch.cpp
@@ -1579,7 +1579,7 @@ int init_catch_param_with_type_int_ptr() {
 // 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:   %[[X_ADDR:.*]] = alloca ptr, align 8
 // OGCG:   %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
 // OGCG:           to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]]
 // OGCG: [[INVOKE_NORMAL]]:
@@ -1615,3 +1615,149 @@ int init_catch_param_with_type_int_ptr() {
 // 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_ref_to_ptr_to_non_record() {
+  int rv = 0;
+  try {
+    division();
+  } catch (int *&p) {
+    rv = *p;
+  }
+  return rv;
+}
+
+// CIR: cir.func {{.*}} @_Z46init_catch_param_with_ref_to_ptr_to_non_recordv() {{.*}} personality(@__gxx_personality_v0)
+// CIR:   %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR:   %[[RV_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["rv", init]
+// CIR:   cir.scope {
+// CIR:     %[[P_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["p", const]
+// CIR:     cir.try {
+// CIR:       %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
+// CIR:       cir.yield
+// CIR:     } catch [type #cir.global_view<@_ZTIPi> : !cir.ptr<!u8i>] (%[[TOKEN:.*]]: !cir.eh_token {{.*}}) {
+// CIR:       %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+// CIR:       cir.cleanup.scope {
+// CIR:         cir.init_catch_param reference %[[TOKEN]] to %[[P_ADDR]] : !cir.eh_token, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
+// CIR:         %[[TMP_P:.*]] = cir.load %[[P_ADDR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
+// CIR:         %[[DEREF_P:.*]] = cir.load deref {{.*}} %[[TMP_P]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR:         %[[P_VAL:.*]] = cir.load {{.*}} %[[DEREF_P]] : !cir.ptr<!s32i>, !s32i
+// CIR:         cir.store {{.*}} %[[P_VAL]], %[[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 @_Z46init_catch_param_with_ref_to_ptr_to_non_recordv() {{.*}} personality ptr @__gxx_personality_v0
+// LLVM:   %[[P_ADDR:.*]] = alloca ptr, i64 1, align 8
+// 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:   %[[EXN_OBJ:.*]] = getelementptr i8, ptr %[[EXN_OBJ_PHI2]], i64 32
+// LLVM:   store ptr %[[EXN_OBJ]], ptr %[[P_ADDR]], align 8
+// LLVM:   %[[TMP_P:.*]] = load ptr, ptr %[[P_ADDR]], align 8
+// LLVM:   %[[DEREF_P:.*]] = load ptr, ptr %[[TMP_P]], align 8
+// LLVM:   %[[P_VAL:.*]] = load i32, ptr %[[DEREF_P]], align 4
+// LLVM:   store i32 %[[P_VAL]], 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 @_Z46init_catch_param_with_ref_to_ptr_to_non_recordv() {{.*}} 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:   %[[P_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:   %[[EXN_OBJ:.*]] = getelementptr i8, ptr %[[TMP_EXCEPTION]], i32 32
+// OGCG:   store ptr %[[EXN_OBJ]], ptr %[[P_ADDR]], align 8
+// OGCG:   %[[TMP_P:.*]] = load ptr, ptr %[[P_ADDR]], align 8
+// OGCG:   %[[DEREF_P:.*]] = load ptr, ptr %[[TMP_P]], align 8
+// OGCG:   %[[P_VAL:.*]] = load i32, ptr %[[DEREF_P]], align 4
+// OGCG:   store i32 %[[P_VAL]], 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]]

@andykaylor andykaylor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're trying to map this too directly onto the classic codegen Itanium handling. The change you're proposing to cir.begin_catch is just a hack to make this work. We want to keep the target-independent abstractions clean and implement things in the correct place during lowering.

In this case, we should be storing the record to the exception variable's alloca during the lowering of cir.construct_catch_param and the cir.init_catch_param will be a noop for this catch type.

Let's hold off on this until I finish landing the cir.construct_catch_param. We'll need to make the copy_fn attribute optional, but otherwise, this should work.

@AmrDeveloper

Copy link
Copy Markdown
Member Author

I think you're trying to map this too directly onto the classic codegen Itanium handling. The change you're proposing to cir.begin_catch is just a hack to make this work. We want to keep the target-independent abstractions clean and implement things in the correct place during lowering.

In this case, we should be storing the record to the exception variable's alloca during the lowering of cir.construct_catch_param and the cir.init_catch_param will be a noop for this catch type.

Let's hold off on this until I finish landing the cir.construct_catch_param. We'll need to make the copy_fn attribute optional, but otherwise, this should work.

My initial idea was that begin_catch with this change will be used only in itantium, but after you landed construct_catch_param, it's clear now that it's a lot better to do it using construct_catch_param, I will update the PR soon

@AmrDeveloper
AmrDeveloper force-pushed the cir_catch_param_ref_non_record branch from d4446aa to d62f9db Compare May 13, 2026 17:19
@AmrDeveloper
AmrDeveloper requested a review from andykaylor May 13, 2026 19:46

@andykaylor andykaylor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. I have just a couple of small suggestions.

Comment thread clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp Outdated
Comment thread clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@AmrDeveloper
AmrDeveloper force-pushed the cir_catch_param_ref_non_record branch from 24174a6 to 7e32692 Compare May 16, 2026 15:12
@AmrDeveloper
AmrDeveloper merged commit 5ea28b0 into llvm:main May 17, 2026
10 checks passed
pedroMVicente pushed a commit to pedroMVicente/llvm-project that referenced this pull request May 19, 2026
…m#195722)

Support init reference type of non-record ptr type in InitCatchParam
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants