[llvm-branch-commits] [clang] [CIR][CodeGen] Share the EH personality selection logic (PR #223421)

Henrich Lauko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Sep 29 04:22:20 PDT 2026


https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223421

>From a6796a67c5975e621cebbb9100ef931d1b2e2e11 Mon Sep 17 00:00:00 2001
From: Henrich Lauko <hlauko at nvidia.com>
Date: Mon, 14 Sep 2026 13:23:49 +0000
Subject: [PATCH] [CIR][CodeGen] Share the EH personality selection logic

Deduplicates the EH personality selection (`getEHPersonality`,
`getCXXEHPersonality`) between CIR and classic CodeGen, taking the classic
implementation. CIR's copy lacked the z/OS, Wasm and GNUstep-on-CygMing cases;
none are reachable in CIR today, so no test changes.
---
 .../clang/CodeGenUtils/EHPersonality.h        |  19 +++
 clang/lib/CIR/CodeGen/CIRGenException.cpp     | 118 +---------------
 clang/lib/CodeGen/CGException.cpp             | 131 +-----------------
 clang/lib/CodeGenUtils/EHPersonality.cpp      | 131 ++++++++++++++++++
 4 files changed, 156 insertions(+), 243 deletions(-)

diff --git a/clang/include/clang/CodeGenUtils/EHPersonality.h b/clang/include/clang/CodeGenUtils/EHPersonality.h
index ab604c801e07e..06e1f8990ec60 100644
--- a/clang/include/clang/CodeGenUtils/EHPersonality.h
+++ b/clang/include/clang/CodeGenUtils/EHPersonality.h
@@ -14,6 +14,13 @@
 #ifndef LLVM_CLANG_CODEGENUTILS_EHPERSONALITY_H
 #define LLVM_CLANG_CODEGENUTILS_EHPERSONALITY_H
 
+namespace clang {
+class CodeGenOptions;
+class FunctionDecl;
+class LangOptions;
+class TargetInfo;
+} // namespace clang
+
 namespace clang::CodeGenUtils {
 
 /// The exceptions personality for a function.
@@ -60,6 +67,18 @@ struct EHPersonality {
   bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; }
 };
 
+/// Selects the personality function to use for \p FD, or for the translation
+/// unit as a whole when \p FD is null.
+const EHPersonality &getEHPersonality(const TargetInfo &Target,
+                                      const LangOptions &LangOpts,
+                                      const CodeGenOptions &CGOpts,
+                                      const FunctionDecl *FD);
+
+/// Selects the personality function that plain C++ would use.  ObjC++ consults
+/// this to decide whether it can fall back on the C++ personality.
+const EHPersonality &getCXXEHPersonality(const TargetInfo &Target,
+                                         const CodeGenOptions &CGOpts);
+
 } // namespace clang::CodeGenUtils
 
 #endif // LLVM_CLANG_CODEGENUTILS_EHPERSONALITY_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index bd3e2014756e6..03ddb343219dd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -22,126 +22,12 @@
 using namespace clang;
 using namespace clang::CIRGen;
 
-static const EHPersonality &getCPersonality(const TargetInfo &target,
-                                            const CodeGenOptions &cgOpts) {
-  const llvm::Triple &triple = target.getTriple();
-  if (triple.isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-  if (cgOpts.hasSjLjExceptions())
-    return EHPersonality::GNU_C_SJLJ;
-  if (cgOpts.hasDWARFExceptions())
-    return EHPersonality::GNU_C;
-  if (cgOpts.hasSEHExceptions())
-    return EHPersonality::GNU_C_SEH;
-  return EHPersonality::GNU_C;
-}
-
-static const EHPersonality &getObjCPersonality(const TargetInfo &target,
-                                               const LangOptions &langOpts,
-                                               const CodeGenOptions &cgOpts) {
-  const llvm::Triple &triple = target.getTriple();
-  if (triple.isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-
-  switch (langOpts.ObjCRuntime.getKind()) {
-  case ObjCRuntime::FragileMacOSX:
-    return getCPersonality(target, cgOpts);
-  case ObjCRuntime::MacOSX:
-  case ObjCRuntime::iOS:
-  case ObjCRuntime::WatchOS:
-    return EHPersonality::NeXT_ObjC;
-  case ObjCRuntime::GNUstep:
-    if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
-      return EHPersonality::GNUstep_ObjC;
-    [[fallthrough]];
-  case ObjCRuntime::GCC:
-  case ObjCRuntime::ObjFW:
-    if (cgOpts.hasSjLjExceptions())
-      return EHPersonality::GNU_ObjC_SJLJ;
-    if (cgOpts.hasSEHExceptions())
-      return EHPersonality::GNU_ObjC_SEH;
-    return EHPersonality::GNU_ObjC;
-  }
-  llvm_unreachable("bad runtime kind");
-}
-
-static const EHPersonality &getCXXPersonality(const TargetInfo &target,
-                                              const CodeGenOptions &cgOpts) {
-  const llvm::Triple &triple = target.getTriple();
-  if (triple.isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-  if (triple.isOSAIX())
-    return EHPersonality::XL_CPlusPlus;
-  if (cgOpts.hasSjLjExceptions())
-    return EHPersonality::GNU_CPlusPlus_SJLJ;
-  if (cgOpts.hasDWARFExceptions())
-    return EHPersonality::GNU_CPlusPlus;
-  if (cgOpts.hasSEHExceptions())
-    return EHPersonality::GNU_CPlusPlus_SEH;
-  if (cgOpts.hasWasmExceptions())
-    return EHPersonality::GNU_Wasm_CPlusPlus;
-  return EHPersonality::GNU_CPlusPlus;
-}
-
-/// Determines the personality function to use when both C++
-/// and Objective-C exceptions are being caught.
-static const EHPersonality &getObjCXXPersonality(const TargetInfo &target,
-                                                 const LangOptions &langOpts,
-                                                 const CodeGenOptions &cgOpts) {
-  if (target.getTriple().isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-
-  switch (langOpts.ObjCRuntime.getKind()) {
-  // In the fragile ABI, just use C++ exception handling and hope
-  // they're not doing crazy exception mixing.
-  case ObjCRuntime::FragileMacOSX:
-    return getCXXPersonality(target, cgOpts);
-
-  // The ObjC personality defers to the C++ personality for non-ObjC
-  // handlers.  Unlike the C++ case, we use the same personality
-  // function on targets using (backend-driven) SJLJ EH.
-  case ObjCRuntime::MacOSX:
-  case ObjCRuntime::iOS:
-  case ObjCRuntime::WatchOS:
-    return getObjCPersonality(target, langOpts, cgOpts);
-
-  case ObjCRuntime::GNUstep:
-    return EHPersonality::GNU_ObjCXX;
-
-  // The GCC runtime's personality function inherently doesn't support
-  // mixed EH.  Use the ObjC personality just to avoid returning null.
-  case ObjCRuntime::GCC:
-  case ObjCRuntime::ObjFW:
-    return getObjCPersonality(target, langOpts, cgOpts);
-  }
-  llvm_unreachable("bad runtime kind");
-}
-
-static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) {
-  return triple.getArch() == llvm::Triple::x86
-             ? EHPersonality::MSVC_except_handler
-             : EHPersonality::MSVC_C_specific_handler;
-}
-
 namespace clang::CIRGen {
 
 const EHPersonality &getEHPersonality(CIRGenModule &cgm,
                                       const FunctionDecl *fd) {
-  const llvm::Triple &triple = cgm.getTarget().getTriple();
-  const LangOptions &langOpts = cgm.getLangOpts();
-  const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
-  const TargetInfo &target = cgm.getTarget();
-
-  // Functions using SEH get an SEH personality.
-  if (fd && fd->usesSEHTry())
-    return getSEHPersonalityMSVC(triple);
-
-  if (langOpts.ObjC) {
-    return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts)
-                              : getObjCPersonality(target, langOpts, cgOpts);
-  }
-  return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts)
-                            : getCPersonality(target, cgOpts);
+  return CodeGenUtils::getEHPersonality(cgm.getTarget(), cgm.getLangOpts(),
+                                        cgm.getCodeGenOpts(), fd);
 }
 
 const EHPersonality &getEHPersonality(CIRGenFunction &cgf) {
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index f8b4cbc516a40..56ebf99f2950b 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -82,136 +82,12 @@ static llvm::FunctionCallee getCatchallRethrowFn(CodeGenModule &CGM,
   return CGM.CreateRuntimeFunction(FTy, Name);
 }
 
-static const EHPersonality &getCPersonality(const TargetInfo &Target,
-                                            const CodeGenOptions &CGOpts) {
-  const llvm::Triple &T = Target.getTriple();
-  if (T.isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-  if (CGOpts.hasSjLjExceptions())
-    return EHPersonality::GNU_C_SJLJ;
-  if (CGOpts.hasDWARFExceptions())
-    return EHPersonality::GNU_C;
-  if (CGOpts.hasSEHExceptions())
-    return EHPersonality::GNU_C_SEH;
-  return EHPersonality::GNU_C;
-}
-
-static const EHPersonality &getObjCPersonality(const TargetInfo &Target,
-                                               const CodeGenOptions &CGOpts,
-                                               const LangOptions &L) {
-  const llvm::Triple &T = Target.getTriple();
-  if (T.isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-  if (T.isWasm())
-    return EHPersonality::GNU_Wasm_CPlusPlus;
-
-  switch (L.ObjCRuntime.getKind()) {
-  case ObjCRuntime::FragileMacOSX:
-    return getCPersonality(Target, CGOpts);
-  case ObjCRuntime::MacOSX:
-  case ObjCRuntime::iOS:
-  case ObjCRuntime::WatchOS:
-    return EHPersonality::NeXT_ObjC;
-  case ObjCRuntime::GNUstep:
-    if (T.isOSCygMing())
-      return EHPersonality::GNU_CPlusPlus_SEH;
-    if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
-      return EHPersonality::GNUstep_ObjC;
-    [[fallthrough]];
-  case ObjCRuntime::GCC:
-  case ObjCRuntime::ObjFW:
-    if (CGOpts.hasSjLjExceptions())
-      return EHPersonality::GNU_ObjC_SJLJ;
-    if (CGOpts.hasSEHExceptions())
-      return EHPersonality::GNU_ObjC_SEH;
-    return EHPersonality::GNU_ObjC;
-  }
-  llvm_unreachable("bad runtime kind");
-}
-
-static const EHPersonality &getCXXPersonality(const TargetInfo &Target,
-                                              const CodeGenOptions &CGOpts) {
-  const llvm::Triple &T = Target.getTriple();
-  if (T.isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-  if (T.isOSAIX())
-    return EHPersonality::XL_CPlusPlus;
-  if (CGOpts.hasSjLjExceptions())
-    return EHPersonality::GNU_CPlusPlus_SJLJ;
-  if (CGOpts.hasDWARFExceptions())
-    return EHPersonality::GNU_CPlusPlus;
-  if (CGOpts.hasSEHExceptions())
-    return EHPersonality::GNU_CPlusPlus_SEH;
-  if (CGOpts.hasWasmExceptions())
-    return EHPersonality::GNU_Wasm_CPlusPlus;
-  if (T.isOSzOS())
-    return EHPersonality::ZOS_CPlusPlus;
-  return EHPersonality::GNU_CPlusPlus;
-}
-
-/// Determines the personality function to use when both C++
-/// and Objective-C exceptions are being caught.
-static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target,
-                                                 const CodeGenOptions &CGOpts,
-                                                 const LangOptions &L) {
-  auto Triple = Target.getTriple();
-  if (Triple.isWindowsMSVCEnvironment())
-    return EHPersonality::MSVC_CxxFrameHandler3;
-  if (Triple.isWasm())
-    return EHPersonality::GNU_Wasm_CPlusPlus;
-
-  switch (L.ObjCRuntime.getKind()) {
-  // In the fragile ABI, just use C++ exception handling and hope
-  // they're not doing crazy exception mixing.
-  case ObjCRuntime::FragileMacOSX:
-    return getCXXPersonality(Target, CGOpts);
-
-  // The ObjC personality defers to the C++ personality for non-ObjC
-  // handlers.  Unlike the C++ case, we use the same personality
-  // function on targets using (backend-driven) SJLJ EH.
-  case ObjCRuntime::MacOSX:
-  case ObjCRuntime::iOS:
-  case ObjCRuntime::WatchOS:
-    return getObjCPersonality(Target, CGOpts, L);
-
-  case ObjCRuntime::GNUstep:
-    if (Triple.isOSCygMing())
-      return EHPersonality::GNU_CPlusPlus_SEH;
-    return EHPersonality::GNU_ObjCXX;
-
-  // The GCC runtime's personality function inherently doesn't support
-  // mixed EH.  Use the ObjC personality just to avoid returning null.
-  case ObjCRuntime::GCC:
-  case ObjCRuntime::ObjFW:
-    return getObjCPersonality(Target, CGOpts, L);
-  }
-  llvm_unreachable("bad runtime kind");
-}
-
-static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &T) {
-  if (T.getArch() == llvm::Triple::x86)
-    return EHPersonality::MSVC_except_handler;
-  return EHPersonality::MSVC_C_specific_handler;
-}
-
 namespace clang::CodeGen {
 
 const EHPersonality &getEHPersonality(CodeGenModule &CGM,
                                       const FunctionDecl *FD) {
-  const llvm::Triple &T = CGM.getTarget().getTriple();
-  const CodeGenOptions &CGOpts = CGM.getCodeGenOpts();
-  const LangOptions &L = CGM.getLangOpts();
-  const TargetInfo &Target = CGM.getTarget();
-
-  // Functions using SEH get an SEH personality.
-  if (FD && FD->usesSEHTry())
-    return getSEHPersonalityMSVC(T);
-
-  if (L.ObjC)
-    return L.CPlusPlus ? getObjCXXPersonality(Target, CGOpts, L)
-                       : getObjCPersonality(Target, CGOpts, L);
-  return L.CPlusPlus ? getCXXPersonality(Target, CGOpts)
-                     : getCPersonality(Target, CGOpts);
+  return CodeGenUtils::getEHPersonality(CGM.getTarget(), CGM.getLangOpts(),
+                                        CGM.getCodeGenOpts(), FD);
 }
 
 const EHPersonality &getEHPersonality(CodeGenFunction &CGF) {
@@ -315,7 +191,8 @@ void CodeGenModule::SimplifyPersonality() {
     return;
 
   const EHPersonality &ObjCXX = getEHPersonality(*this, /*FD=*/nullptr);
-  const EHPersonality &CXX = getCXXPersonality(getTarget(), CodeGenOpts);
+  const EHPersonality &CXX =
+      CodeGenUtils::getCXXEHPersonality(getTarget(), CodeGenOpts);
   if (&ObjCXX == &CXX)
     return;
 
diff --git a/clang/lib/CodeGenUtils/EHPersonality.cpp b/clang/lib/CodeGenUtils/EHPersonality.cpp
index ee9fe010c98a7..4fa247cfdb864 100644
--- a/clang/lib/CodeGenUtils/EHPersonality.cpp
+++ b/clang/lib/CodeGenUtils/EHPersonality.cpp
@@ -7,6 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/CodeGenUtils/EHPersonality.h"
+#include "clang/AST/Decl.h"
+#include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
 
 namespace clang::CodeGenUtils {
 
@@ -46,4 +50,131 @@ const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
 const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
                                                     nullptr};
 
+static const EHPersonality &getCPersonality(const TargetInfo &Target,
+                                            const CodeGenOptions &CGOpts) {
+  const llvm::Triple &T = Target.getTriple();
+  if (T.isWindowsMSVCEnvironment())
+    return EHPersonality::MSVC_CxxFrameHandler3;
+  if (CGOpts.hasSjLjExceptions())
+    return EHPersonality::GNU_C_SJLJ;
+  if (CGOpts.hasDWARFExceptions())
+    return EHPersonality::GNU_C;
+  if (CGOpts.hasSEHExceptions())
+    return EHPersonality::GNU_C_SEH;
+  return EHPersonality::GNU_C;
+}
+
+static const EHPersonality &getObjCPersonality(const TargetInfo &Target,
+                                               const CodeGenOptions &CGOpts,
+                                               const LangOptions &L) {
+  const llvm::Triple &T = Target.getTriple();
+  if (T.isWindowsMSVCEnvironment())
+    return EHPersonality::MSVC_CxxFrameHandler3;
+  if (T.isWasm())
+    return EHPersonality::GNU_Wasm_CPlusPlus;
+
+  switch (L.ObjCRuntime.getKind()) {
+  case ObjCRuntime::FragileMacOSX:
+    return getCPersonality(Target, CGOpts);
+  case ObjCRuntime::MacOSX:
+  case ObjCRuntime::iOS:
+  case ObjCRuntime::WatchOS:
+    return EHPersonality::NeXT_ObjC;
+  case ObjCRuntime::GNUstep:
+    if (T.isOSCygMing())
+      return EHPersonality::GNU_CPlusPlus_SEH;
+    if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
+      return EHPersonality::GNUstep_ObjC;
+    [[fallthrough]];
+  case ObjCRuntime::GCC:
+  case ObjCRuntime::ObjFW:
+    if (CGOpts.hasSjLjExceptions())
+      return EHPersonality::GNU_ObjC_SJLJ;
+    if (CGOpts.hasSEHExceptions())
+      return EHPersonality::GNU_ObjC_SEH;
+    return EHPersonality::GNU_ObjC;
+  }
+  llvm_unreachable("bad runtime kind");
+}
+
+const EHPersonality &getCXXEHPersonality(const TargetInfo &Target,
+                                         const CodeGenOptions &CGOpts) {
+  const llvm::Triple &T = Target.getTriple();
+  if (T.isWindowsMSVCEnvironment())
+    return EHPersonality::MSVC_CxxFrameHandler3;
+  if (T.isOSAIX())
+    return EHPersonality::XL_CPlusPlus;
+  if (CGOpts.hasSjLjExceptions())
+    return EHPersonality::GNU_CPlusPlus_SJLJ;
+  if (CGOpts.hasDWARFExceptions())
+    return EHPersonality::GNU_CPlusPlus;
+  if (CGOpts.hasSEHExceptions())
+    return EHPersonality::GNU_CPlusPlus_SEH;
+  if (CGOpts.hasWasmExceptions())
+    return EHPersonality::GNU_Wasm_CPlusPlus;
+  if (T.isOSzOS())
+    return EHPersonality::ZOS_CPlusPlus;
+  return EHPersonality::GNU_CPlusPlus;
+}
+
+/// Determines the personality function to use when both C++
+/// and Objective-C exceptions are being caught.
+static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target,
+                                                 const CodeGenOptions &CGOpts,
+                                                 const LangOptions &L) {
+  auto Triple = Target.getTriple();
+  if (Triple.isWindowsMSVCEnvironment())
+    return EHPersonality::MSVC_CxxFrameHandler3;
+  if (Triple.isWasm())
+    return EHPersonality::GNU_Wasm_CPlusPlus;
+
+  switch (L.ObjCRuntime.getKind()) {
+  // In the fragile ABI, just use C++ exception handling and hope
+  // they're not doing crazy exception mixing.
+  case ObjCRuntime::FragileMacOSX:
+    return getCXXEHPersonality(Target, CGOpts);
+
+  // The ObjC personality defers to the C++ personality for non-ObjC
+  // handlers.  Unlike the C++ case, we use the same personality
+  // function on targets using (backend-driven) SJLJ EH.
+  case ObjCRuntime::MacOSX:
+  case ObjCRuntime::iOS:
+  case ObjCRuntime::WatchOS:
+    return getObjCPersonality(Target, CGOpts, L);
+
+  case ObjCRuntime::GNUstep:
+    if (Triple.isOSCygMing())
+      return EHPersonality::GNU_CPlusPlus_SEH;
+    return EHPersonality::GNU_ObjCXX;
+
+  // The GCC runtime's personality function inherently doesn't support
+  // mixed EH.  Use the ObjC personality just to avoid returning null.
+  case ObjCRuntime::GCC:
+  case ObjCRuntime::ObjFW:
+    return getObjCPersonality(Target, CGOpts, L);
+  }
+  llvm_unreachable("bad runtime kind");
+}
+
+static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &T) {
+  if (T.getArch() == llvm::Triple::x86)
+    return EHPersonality::MSVC_except_handler;
+  return EHPersonality::MSVC_C_specific_handler;
+}
+
+const EHPersonality &getEHPersonality(const TargetInfo &Target,
+                                      const LangOptions &LangOpts,
+                                      const CodeGenOptions &CGOpts,
+                                      const FunctionDecl *FD) {
+  // Functions using SEH get an SEH personality.
+  if (FD && FD->usesSEHTry())
+    return getSEHPersonalityMSVC(Target.getTriple());
+
+  if (LangOpts.ObjC)
+    return LangOpts.CPlusPlus ? getObjCXXPersonality(Target, CGOpts, LangOpts)
+                              : getObjCPersonality(Target, CGOpts, LangOpts);
+  return LangOpts.CPlusPlus ? getCXXEHPersonality(Target, CGOpts)
+                            : getCPersonality(Target, CGOpts);
+}
+
 } // namespace clang::CodeGenUtils



More information about the llvm-branch-commits mailing list