-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Objective C: use C++ exceptions on MinGW+GNUstep #77255
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write If you have received no comments on your PR for a week, you can request a review If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Frederik Carlier (qmfrederik) ChangesThe GNUstep Objective C runtime (libobjc2) is adding support for MinGW. This runtime uses C++ exceptions in that configuration. Full diff: https://github.com/llvm/llvm-project/pull/77255.diff 3 Files Affected:
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..5ace469c927045 100644
--- a/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -819,7 +819,15 @@ 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) {
+ 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);
@@ -2210,7 +2218,11 @@ 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 +2399,7 @@ 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 +4005,7 @@ 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
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
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
62d7da8
to
d04a411
Compare
/cc @davidchisnall |
4212c79
to
d5dec27
Compare
d5dec27
to
6195e6c
Compare
The failing format CI isn’t in this PR, rebasing to (hopefully) fix it |
clang/lib/CodeGen/CGException.cpp
Outdated
if (Target.getTriple().isOSCygMing()) | ||
return EHPersonality::GNU_CPlusPlus_SEH; | ||
else | ||
return EHPersonality::GNU_ObjCXX; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be nicer as a ternary return.
clang/lib/CodeGen/CGObjCGNU.cpp
Outdated
// void objc_exception_rethrow(void*) | ||
ExceptionReThrowFn.init(&CGM, "__cxa_rethrow", PtrTy); | ||
} else if (usesSEHExceptions) { | ||
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not hoist this? It is used across multiple branches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good remark, thanks. Fixed this.
clang/lib/CodeGen/CGObjCGNU.cpp
Outdated
if (isRethrow && usesSEHExceptions) { | ||
if (isRethrow && | ||
(usesSEHExceptions || (CGM.getTarget().getTriple().isOSCygMing() && | ||
isRuntime(ObjCRuntime::GNUstep, 2)))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to introduce a usesCxxExceptions
variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that makes the intent clearer. I changed this.
6eda9f3
to
8ff9bb0
Compare
@compnerd Thanks for you feedback, I addressed your comments. |
2a97fae
to
a961488
Compare
@compnerd @davidchisnall I've addressed the feedback and CI is (mostly) green. The build failure on Windows seems unrelated:
|
I'd like CI to be green. Hopefully the failure is transient, but I don't seem to be able to kick off a rerun. Maybe once others start passing, you can squash the two commits and force push to restart it? |
a961488
to
be6dccb
Compare
Looks like there was an intermittent issue with GitHub, which should be resolved now. I've squashed and pushed. Fingers crossed! |
CI looks green, let me know if there's anything else you need from me on this PR! |
clang/lib/CodeGen/CGObjCGNU.cpp
Outdated
@@ -2210,7 +2219,11 @@ 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 (usesCxxExceptions) { | |||
ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, IdTy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say that a ternary to select between the exception model and identify the name would be better as you are just selecting the label.
3a7edda
to
f1f12fb
Compare
f1f12fb
to
d0d2e2f
Compare
It looks as if three tests are failing in CI: Clang :: CodeGenObjC/2007-04-03-ObjcEH.m |
d0d2e2f
to
4d41874
Compare
The GNUstep Objective C runtime (libobjc2) is adding support for MinGW. This runtime uses C++ exceptions in that configuration.
4d41874
to
9ede4ec
Compare
@davidchisnall Apologies, that was a fat-finger mistake while addressing the latest feedback. CI is green now. |
The GNUstep Objective C runtime (libobjc2) is adding support for the GNU ABI on Windows (more specifically, MinGW). The libobjc2 runtime uses C++ exceptions in that configuration; this PR updates clang to act accordingly. The corresponding change to libobjc2 is here: gnustep/libobjc2#267
The GNUstep Objective C runtime (libobjc2) is adding support for the GNU ABI on Windows (more specifically, MinGW). The libobjc2 runtime uses C++ exceptions in that configuration; this PR updates clang to act accordingly.
The corresponding change to libobjc2 is here: gnustep/libobjc2#267