https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223421
>From caa082d197937baacfceac712f62f54c568cccba Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
