https://github.com/qmfrederik updated https://github.com/llvm/llvm-project/pull/77255
>From d04a41177e9c39799b73168d397dd87fb948caa1 Mon Sep 17 00:00:00 2001 From: Frederik Carlier <frederik.carl...@keysight.com> Date: Thu, 4 Jan 2024 11:10:05 -0800 Subject: [PATCH] Objective C: use C++ exceptions on MinGW+GNUstep The GNUstep Objective C runtime (libobjc2) is adding support for MinGW. This runtime uses C++ exceptions in that configuration. --- clang/lib/CodeGen/CGException.cpp | 18 ++++--- clang/lib/CodeGen/CGObjCGNU.cpp | 35 ++++++++---- .../test/CodeGenObjC/exceptions-personality.m | 53 +++++++++++++++++++ 3 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 clang/test/CodeGenObjC/exceptions-personality.m diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 0d507da5c1ba92..939f7962dcc635 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -145,8 +145,6 @@ static const EHPersonality &getCPersonality(const TargetInfo &Target, static const EHPersonality &getObjCPersonality(const TargetInfo &Target, const LangOptions &L) { const llvm::Triple &T = Target.getTriple(); - if (T.isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; switch (L.ObjCRuntime.getKind()) { case ObjCRuntime::FragileMacOSX: @@ -156,7 +154,11 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target, case ObjCRuntime::WatchOS: return EHPersonality::NeXT_ObjC; case ObjCRuntime::GNUstep: - if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) + if (T.isOSCygMing()) + return EHPersonality::GNU_CPlusPlus_SEH; + else if (T.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + else if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) return EHPersonality::GNUstep_ObjC; [[fallthrough]]; case ObjCRuntime::GCC: @@ -192,9 +194,6 @@ static const EHPersonality &getCXXPersonality(const TargetInfo &Target, /// and Objective-C exceptions are being caught. static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, const LangOptions &L) { - if (Target.getTriple().isWindowsMSVCEnvironment()) - return EHPersonality::MSVC_CxxFrameHandler3; - switch (L.ObjCRuntime.getKind()) { // In the fragile ABI, just use C++ exception handling and hope // they're not doing crazy exception mixing. @@ -210,7 +209,12 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target, return getObjCPersonality(Target, L); case ObjCRuntime::GNUstep: - return EHPersonality::GNU_ObjCXX; + if (Target.getTriple().isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + else if (Target.getTriple().isOSCygMing()) + return EHPersonality::GNU_CPlusPlus_SEH; + else + 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. diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 4ca1a8cce64d89..2b3a5da87fb778 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -819,10 +819,19 @@ class CGObjCGNUstep : public CGObjCGNU { SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, PtrToObjCSuperTy, SelectorTy); // If we're in ObjC++ mode, then we want to make - if (usesSEHExceptions) { - llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); - // void objc_exception_rethrow(void) - ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy); + if (CGM.getTarget().getTriple().isOSCygMing() && + isRuntime(ObjCRuntime::GNUstep, 2)) { + llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); + // void *__cxa_begin_catch(void *e) + EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy); + // void __cxa_end_catch(void) + ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy); + // void objc_exception_rethrow(void*) + ExceptionReThrowFn.init(&CGM, "__cxa_rethrow", PtrTy); + } else if (usesSEHExceptions) { + llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); + // void objc_exception_rethrow(void) + ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy); } else if (CGM.getLangOpts().CPlusPlus) { llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // void *__cxa_begin_catch(void *e) @@ -2210,7 +2219,12 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, // void objc_exception_throw(id); ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); - ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); + if ((CGM.getTarget().getTriple().isOSCygMing() && + isRuntime(ObjCRuntime::GNUstep, 2))) { + ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, IdTy); + } else { + ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy); + } // int objc_sync_enter(id); SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy); // int objc_sync_exit(id); @@ -2387,7 +2401,9 @@ llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) { if (usesSEHExceptions) return CGM.getCXXABI().getAddrOfRTTIDescriptor(T); - if (!CGM.getLangOpts().CPlusPlus) + if (!CGM.getLangOpts().CPlusPlus && + !(CGM.getTarget().getTriple().isOSCygMing() && + isRuntime(ObjCRuntime::GNUstep, 2))) return CGObjCGNU::GetEHType(T); // For Objective-C++, we want to provide the ability to catch both C++ and @@ -3993,7 +4009,9 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, ExceptionAsObject = CGF.ObjCEHValueStack.back(); isRethrow = true; } - if (isRethrow && usesSEHExceptions) { + if (isRethrow && + (usesSEHExceptions || (CGM.getTarget().getTriple().isOSCygMing() && + isRuntime(ObjCRuntime::GNUstep, 2)))) { // For SEH, ExceptionAsObject may be undef, because the catch handler is // not passed it for catchalls and so it is not visible to the catch // funclet. The real thrown object will still be live on the stack at this @@ -4003,8 +4021,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, // argument. llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn); Throw->setDoesNotReturn(); - } - else { + } else { ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy); llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); diff --git a/clang/test/CodeGenObjC/exceptions-personality.m b/clang/test/CodeGenObjC/exceptions-personality.m new file mode 100644 index 00000000000000..c29f7483715d88 --- /dev/null +++ b/clang/test/CodeGenObjC/exceptions-personality.m @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-MINGW-OBJC2 < %t %s + +// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-MINGW-GCC < %t %s + +// RUN: %clang_cc1 -triple x86_64-w64-windows-msvc -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-MSVC-OBJC2 < %t %s + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-LINUX-OBJC2 < %t %s + +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck --check-prefixes=CHECK-LINUX-GCC < %t %s +@interface Foo @end + +void throwing(void) { + @try + { + // CHECK-MINGW-OBJC2: personality ptr @__gxx_personality_seh0 + // CHECK-MINGW-OBJC2: invoke void @objc_exception_throw + + // CHECK-MINGW-GCC: personality ptr @__gnu_objc_personality_v0 + // CHECK-MINGW-GCC: invoke void @objc_exception_throw + + // CHECK-MSVC-OBJC2: personality ptr @__CxxFrameHandler3 + // CHECK-MSVC-OBJC2: invoke void @objc_exception_throw + + // CHECK-LINUX-OBJC2: personality ptr @__gnustep_objc_personality_v0 + // CHECK-LINUX-OBJC2: invoke void @objc_exception_throw + + // CHECK-LINUX-GCC: personality ptr @__gnu_objc_personality_v0 + @throw(@"error!"); + } + @catch(...) + { + // CHECK-MINGW-OBJC2: call ptr @__cxa_begin_catch + // CHECK-MINGW-OBJC2: invoke ptr @__cxa_rethrow + // CHECK-MINGW-OBJC2: invoke void @__cxa_end_catch + + // CHECK-MINGW-GCC: call void @objc_exception_throw + + // CHECK-MSVC-OBJC2: call void @objc_exception_rethrow + + // CHECK-LINUX-OBJC2: call ptr @objc_begin_catch + // CHECK-LINUX-OBJC2: invoke void @objc_exception_throw + // CHECK-LINUX-OBJC2: invoke void @objc_end_catch() + + // CHECK-LINUX-GCC: invoke void @objc_exception_throw + + @throw; + } +} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits