[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
Mon Sep 21 06:36:06 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223421
>From 0306b8a972dae4cb258bd2a969b06b00044d6380 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
Takes the classic implementation as the shared one and turns both
getEHPersonality entry points into forwarders.
CIR's copies had drifted and were missing five cases that classic CodeGen
handles: ZOS_CPlusPlus on z/OS, GNU_Wasm_CPlusPlus on Wasm, and
GNU_CPlusPlus_SEH for GNUstep on CygMing, the last two in both the ObjC and
ObjC++ paths. None are reachable in CIR today, so there is no observable
change and no test to add. z/OS uses the XL C++ ABI and Wasm its own, and
CIRGenModule's createCXXABI rejects both with an NYI error before any
function is emitted. Objective-C is not implemented, and CygMing hits
"NYI: shouldAssumeDSOLocal: MinGW". Sharing the code now means CIR picks up
the right personality once those targets work, rather than silently
emitting __gxx_personality_v0.
No change in test output.
---
.../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