[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:25:47 PDT 2026
https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223421
>From d948962d3110215f15a4ea1a10eaafb99a34fc3c 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.
Assisted-by: Claude Code (Claude Fable 5.1).
---
.../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