r174940 - Call __cxa_begin_catch with the current exception before
John McCall
rjmccall at apple.com
Mon Feb 11 19:51:46 PST 2013
Author: rjmccall
Date: Mon Feb 11 21:51:46 2013
New Revision: 174940
URL: http://llvm.org/viewvc/llvm-project?rev=174940&view=rev
Log:
Call __cxa_begin_catch with the current exception before
calling std::terminate(). rdar://11904428
Modified:
cfe/trunk/lib/CodeGen/CGException.cpp
cfe/trunk/test/CXX/except/except.spec/p9-noexcept.cpp
cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
cfe/trunk/test/CodeGenCXX/exceptions.cpp
cfe/trunk/test/CodeGenCXX/nrvo.cpp
Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=174940&r1=174939&r2=174940&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Mon Feb 11 21:51:46 2013
@@ -1516,6 +1516,65 @@ void CodeGenFunction::FinallyInfo::exit(
CGF.PopCleanupBlock();
}
+/// In a terminate landing pad, should we use __clang__call_terminate
+/// or just a naked call to std::terminate?
+///
+/// __clang_call_terminate calls __cxa_begin_catch, which then allows
+/// std::terminate to usefully report something about the
+/// violating exception.
+static bool useClangCallTerminate(CodeGenModule &CGM) {
+ // Only do this for Itanium-family ABIs in C++ mode.
+ return (CGM.getLangOpts().CPlusPlus &&
+ CGM.getTarget().getCXXABI().isItaniumFamily());
+}
+
+/// Get or define the following function:
+/// void @__clang_call_terminate(i8* %exn) nounwind noreturn
+/// This code is used only in C++.
+static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {
+ llvm::FunctionType *fnTy =
+ llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
+ llvm::Constant *fnRef =
+ CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate");
+
+ llvm::Function *fn = dyn_cast<llvm::Function>(fnRef);
+ if (fn && fn->empty()) {
+ fn->setDoesNotThrow();
+ fn->setDoesNotReturn();
+
+ // What we really want is to massively penalize inlining without
+ // forbidding it completely. The difference between that and
+ // 'noinline' is negligible.
+ fn->addFnAttr(llvm::Attribute::NoInline);
+
+ // Allow this function to be shared across translation units, but
+ // we don't want it to turn into an exported symbol.
+ fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
+ fn->setVisibility(llvm::Function::HiddenVisibility);
+
+ // Set up the function.
+ llvm::BasicBlock *entry =
+ llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
+ CGBuilderTy builder(entry);
+
+ // Pull the exception pointer out of the parameter list.
+ llvm::Value *exn = &*fn->arg_begin();
+
+ // Call __cxa_begin_catch(exn).
+ builder.CreateCall(getBeginCatchFn(CGM), exn)->setDoesNotThrow();
+
+ // Call std::terminate().
+ llvm::CallInst *termCall = builder.CreateCall(getTerminateFn(CGM));
+ termCall->setDoesNotThrow();
+ termCall->setDoesNotReturn();
+
+ // std::terminate cannot return.
+ builder.CreateUnreachable();
+ }
+
+ return fnRef;
+}
+
llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
if (TerminateLandingPad)
return TerminateLandingPad;
@@ -1533,9 +1592,16 @@ llvm::BasicBlock *CodeGenFunction::getTe
getOpaquePersonalityFn(CGM, Personality), 0);
LPadInst->addClause(getCatchAllValue(*this));
- llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(CGM));
- TerminateCall->setDoesNotReturn();
- TerminateCall->setDoesNotThrow();
+ llvm::CallInst *terminateCall;
+ if (useClangCallTerminate(CGM)) {
+ // Extract out the exception pointer.
+ llvm::Value *exn = Builder.CreateExtractValue(LPadInst, 0);
+ terminateCall = Builder.CreateCall(getClangCallTerminateFn(CGM), exn);
+ } else {
+ terminateCall = Builder.CreateCall(getTerminateFn(CGM));
+ }
+ terminateCall->setDoesNotReturn();
+ terminateCall->setDoesNotThrow();
Builder.CreateUnreachable();
// Restore the saved insertion state.
Modified: cfe/trunk/test/CXX/except/except.spec/p9-noexcept.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p9-noexcept.cpp?rev=174940&r1=174939&r2=174940&view=diff
==============================================================================
--- cfe/trunk/test/CXX/except/except.spec/p9-noexcept.cpp (original)
+++ cfe/trunk/test/CXX/except/except.spec/p9-noexcept.cpp Mon Feb 11 21:51:46 2013
@@ -7,9 +7,10 @@ void target() noexcept
// CHECK: invoke void @_Z8externalv()
external();
}
-// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK: [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
// CHECK-NEXT: catch i8* null
-// CHECK-NEXT: call void @_ZSt9terminatev() noreturn nounwind
+// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
+// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T1]]) noreturn nounwind
// CHECK-NEXT: unreachable
void reverse() noexcept(false)
Modified: cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp?rev=174940&r1=174939&r2=174940&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp Mon Feb 11 21:51:46 2013
@@ -29,12 +29,12 @@ delegator::delegator(bool)
// CHECK: define {{.*}} @_ZN9delegatorC1Ec
// CHECK: {{.*}} @_ZN9delegatorC1Eb
// CHECK: void @__cxa_throw
-// CHECK: void @_ZSt9terminatev
+// CHECK: void @__clang_call_terminate
// CHECK: {{.*}} @_ZN9delegatorD1Ev
// CHECK: define {{.*}} @_ZN9delegatorC2Ec
// CHECK: {{.*}} @_ZN9delegatorC2Eb
// CHECK: void @__cxa_throw
-// CHECK: void @_ZSt9terminatev
+// CHECK: void @__clang_call_terminate
// CHECK: {{.*}} @_ZN9delegatorD2Ev
delegator::delegator(char)
: delegator(true) {
Modified: cfe/trunk/test/CodeGenCXX/exceptions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/exceptions.cpp?rev=174940&r1=174939&r2=174940&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/exceptions.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/exceptions.cpp Mon Feb 11 21:51:46 2013
@@ -69,6 +69,13 @@ namespace test1 {
return new A(B().x);
}
+ // rdar://11904428
+ // Terminate landing pads should call __cxa_begin_catch first.
+ // CHECK: define linkonce_odr hidden void @__clang_call_terminate(i8*) noinline noreturn nounwind
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @__cxa_begin_catch(i8* %0) nounwind
+ // CHECK-NEXT: call void @_ZSt9terminatev() noreturn nounwind
+ // CHECK-NEXT: unreachable
+
A *d() {
// CHECK: define [[A:%.*]]* @_ZN5test11dEv()
// CHECK: [[ACTIVE:%.*]] = alloca i1
@@ -157,7 +164,7 @@ namespace test2 {
// CHECK-NEXT: invoke void @_ZN5test21AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
// CHECK: invoke void @_ZN5test21AdlEPvm(i8* [[NEW]], i64 8)
- // CHECK: call void @_ZSt9terminatev()
+ // CHECK: call void @__clang_call_terminate(i8* {{%.*}}) noreturn nounwind
return new A(5);
}
}
@@ -183,7 +190,7 @@ namespace test3 {
// CHECK-NEXT: invoke void @_ZN5test31AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
// CHECK: invoke void @_ZN5test31AdlEPvS1_d(i8* [[NEW]], i8* [[FOO]], double [[BAR]])
- // CHECK: call void @_ZSt9terminatev()
+ // CHECK: call void @__clang_call_terminate(i8* {{%.*}}) noreturn nounwind
return new(foo(),bar()) A(5);
}
Modified: cfe/trunk/test/CodeGenCXX/nrvo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/nrvo.cpp?rev=174940&r1=174939&r2=174940&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/nrvo.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/nrvo.cpp Mon Feb 11 21:51:46 2013
@@ -100,9 +100,10 @@ X test2(bool B) {
// CHECK-EH: resume { i8*, i32 }
// %terminate.lpad: terminate landing pad.
- // CHECK-EH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ // CHECK-EH: [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
// CHECK-EH-NEXT: catch i8* null
- // CHECK-EH-NEXT: call void @_ZSt9terminatev()
+ // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
+ // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) noreturn nounwind
// CHECK-EH-NEXT: unreachable
}
More information about the cfe-commits
mailing list