Author: Amr Hesham
Date: 2025-10-25T13:40:47+02:00
New Revision: b0658b1151a7dce63e7bc29b69037462c07c355e

URL: 
https://github.com/llvm/llvm-project/commit/b0658b1151a7dce63e7bc29b69037462c07c355e
DIFF: 
https://github.com/llvm/llvm-project/commit/b0658b1151a7dce63e7bc29b69037462c07c355e.diff

LOG: [CIR][NFC] Upstream EHPersonality for function (#164883)

Upstream the EHPersonality class for a function as a prerequisite for
working with the handlers

Issue #154992

Added: 
    

Modified: 
    clang/lib/CIR/CodeGen/CIRGenCleanup.h
    clang/lib/CIR/CodeGen/CIRGenException.cpp
    clang/lib/CIR/CodeGen/CIRGenFunction.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.h 
b/clang/lib/CIR/CodeGen/CIRGenCleanup.h
index 9acf8b1f20e79..61a09a59b05c0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCleanup.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.h
@@ -15,6 +15,7 @@
 #define CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H
 
 #include "Address.h"
+#include "CIRGenModule.h"
 #include "EHScopeStack.h"
 #include "mlir/IR/Value.h"
 
@@ -257,5 +258,53 @@ inline void EHScopeStack::popCatch() {
   deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
 }
 
+/// The exceptions personality for a function.
+struct EHPersonality {
+  const char *personalityFn = nullptr;
+
+  // If this is non-null, this personality requires a non-standard
+  // function for rethrowing an exception after a catchall cleanup.
+  // This function must have prototype void(void*).
+  const char *catchallRethrowFn = nullptr;
+
+  static const EHPersonality &get(CIRGenModule &cgm,
+                                  const clang::FunctionDecl *fd);
+  static const EHPersonality &get(CIRGenFunction &cgf);
+
+  static const EHPersonality GNU_C;
+  static const EHPersonality GNU_C_SJLJ;
+  static const EHPersonality GNU_C_SEH;
+  static const EHPersonality GNU_ObjC;
+  static const EHPersonality GNU_ObjC_SJLJ;
+  static const EHPersonality GNU_ObjC_SEH;
+  static const EHPersonality GNUstep_ObjC;
+  static const EHPersonality GNU_ObjCXX;
+  static const EHPersonality NeXT_ObjC;
+  static const EHPersonality GNU_CPlusPlus;
+  static const EHPersonality GNU_CPlusPlus_SJLJ;
+  static const EHPersonality GNU_CPlusPlus_SEH;
+  static const EHPersonality MSVC_except_handler;
+  static const EHPersonality MSVC_C_specific_handler;
+  static const EHPersonality MSVC_CxxFrameHandler3;
+  static const EHPersonality GNU_Wasm_CPlusPlus;
+  static const EHPersonality XL_CPlusPlus;
+  static const EHPersonality ZOS_CPlusPlus;
+
+  /// Does this personality use landingpads or the family of pad instructions
+  /// designed to form funclets?
+  bool usesFuncletPads() const {
+    return isMSVCPersonality() || isWasmPersonality();
+  }
+
+  bool isMSVCPersonality() const {
+    return this == &MSVC_except_handler || this == &MSVC_C_specific_handler ||
+           this == &MSVC_CxxFrameHandler3;
+  }
+
+  bool isWasmPersonality() const { return this == &GNU_Wasm_CPlusPlus; }
+
+  bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; }
+};
+
 } // namespace clang::CIRGen
 #endif // CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H

diff  --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp 
b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index 717a3e0032cea..67f46ffde8fda 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -18,6 +18,171 @@
 using namespace clang;
 using namespace clang::CIRGen;
 
+const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr};
+const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0",
+                                                 nullptr};
+const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0",
+                                                nullptr};
+const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0",
+                                                nullptr};
+const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0",
+                                                    nullptr};
+const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ = {
+    "__gxx_personality_sj0", nullptr};
+const EHPersonality EHPersonality::GNU_CPlusPlus_SEH = {
+    "__gxx_personality_seh0", nullptr};
+const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0",
+                                               "objc_exception_throw"};
+const EHPersonality EHPersonality::GNU_ObjC_SJLJ = {
+    "__gnu_objc_personality_sj0", "objc_exception_throw"};
+const EHPersonality EHPersonality::GNU_ObjC_SEH = {
+    "__gnu_objc_personality_seh0", "objc_exception_throw"};
+const EHPersonality EHPersonality::GNU_ObjCXX = {
+    "__gnustep_objcxx_personality_v0", nullptr};
+const EHPersonality EHPersonality::GNUstep_ObjC = {
+    "__gnustep_objc_personality_v0", nullptr};
+const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3",
+                                                          nullptr};
+const EHPersonality EHPersonality::MSVC_C_specific_handler = {
+    "__C_specific_handler", nullptr};
+const EHPersonality EHPersonality::MSVC_CxxFrameHandler3 = {
+    "__CxxFrameHandler3", nullptr};
+const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = {
+    "__gxx_wasm_personality_v0", nullptr};
+const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
+                                                   nullptr};
+const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
+                                                    nullptr};
+
+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;
+}
+
+const EHPersonality &EHPersonality::get(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);
+}
+
+const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) {
+  const auto *fg = cgf.curCodeDecl;
+  // For outlined finallys and filters, use the SEH personality in case they
+  // contain more SEH. This mostly only affects finallys. Filters could
+  // hypothetically use gnu statement expressions to sneak in nested SEH.
+  fg = fg ? fg : cgf.curSEHParent.getDecl();
+  return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
+}
+
 void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) {
   const llvm::Triple &triple = getTarget().getTriple();
   if (cgm.getLangOpts().OpenMPIsTargetDevice &&

diff  --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index d7911302df45c..c3fcd1a69a88e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -120,6 +120,8 @@ class CIRGenFunction : public CIRGenTypeCache {
   /// Tracks function scope overall cleanup handling.
   EHScopeStack ehStack;
 
+  GlobalDecl curSEHParent;
+
   llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
       lambdaCaptureFields;
   clang::FieldDecl *lambdaThisCaptureField = nullptr;


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to