From 285cfd8953d4ca4da613a47a0d691f7234068f8c Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Mon, 19 Sep 2011 20:31:14 +0000 Subject: [PATCH] Throw the switch to convert clang to the new exception handling model! This model uses the 'landingpad' instruction, which is pinned to the top of the landing pad. (A landing pad is defined as the destination of the unwind branch of an invoke instruction.) All of the information needed to generate the correct exception handling metadata during code generation is encoded into the landingpad instruction. The new 'resume' instruction takes the place of the llvm.eh.resume intrinsic call. It's lowered in much the same way as the intrinsic is. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140049 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGException.cpp | 113 +++++++++--------- lib/CodeGen/CodeGenFunction.cpp | 5 +- lib/CodeGen/CodeGenFunction.h | 12 +- test/CXX/except/except.spec/p9-dynamic.cpp | 5 +- test/CXX/except/except.spec/p9-noexcept.cpp | 3 +- test/CodeGen/exceptions.c | 6 +- test/CodeGenCXX/arm.cpp | 10 +- test/CodeGenCXX/destructors.cpp | 10 +- test/CodeGenCXX/dynamic-cast.cpp | 3 +- test/CodeGenCXX/eh.cpp | 17 ++- test/CodeGenCXX/nrvo.cpp | 13 +- test/CodeGenCXX/partial-destruction.cpp | 18 ++- .../threadsafe-statics-exceptions.cpp | 7 +- test/CodeGenCXX/typeid.cpp | 3 +- test/CodeGenObjC/blocks-2.m | 5 +- test/CodeGenObjC/gnu-exceptions.m | 6 +- test/CodeGenObjC/terminate.m | 8 +- test/CodeGenObjCXX/catch-id-type.mm | 5 +- test/CodeGenObjCXX/exceptions.mm | 3 +- 19 files changed, 138 insertions(+), 114 deletions(-) diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index e711914955..14a89cff3f 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -306,12 +306,6 @@ static llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) { return llvm::ConstantPointerNull::get(CGF.Int8PtrTy); } -/// Returns the value to inject into a selector to indicate the -/// presence of a cleanup. -static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) { - return llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); -} - namespace { /// A cleanup to free the exception object if its initialization /// throws. @@ -733,17 +727,19 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { llvm::BasicBlock *lpad = createBasicBlock("lpad"); EmitBlock(lpad); + llvm::LandingPadInst *LPadInst = + Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL), + getOpaquePersonalityFn(CGM, personality), 0); + + llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0); + Builder.CreateStore(LPadExn, getExceptionSlot()); + llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1); + Builder.CreateStore(LPadSel, getEHSelectorSlot()); + // Save the exception pointer. It's safe to use a single exception // pointer per function because EH cleanups can never have nested // try/catches. - llvm::CallInst *exn = - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn"); - exn->setDoesNotThrow(); - - // Build the selector arguments. - SmallVector selector; - selector.push_back(exn); - selector.push_back(getOpaquePersonalityFn(CGM, personality)); + // Build the landingpad instruction. // Accumulate all the handlers in scope. bool hasCatchAll = false; @@ -764,7 +760,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); assert(!hasCatchAll && "EH filter reached after catch-all"); - // Filter scopes get added to the selector in weird ways. + // Filter scopes get added to the landingpad in weird ways. EHFilterScope &filter = cast(*I); hasFilter = true; @@ -800,54 +796,52 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { } // Check whether we already have a handler for this type. - if (catchTypes.insert(handler.Type)) { - // If not, add it directly to the selector. - selector.push_back(handler.Type); - } + if (catchTypes.insert(handler.Type)) + // If not, add it directly to the landingpad. + LPadInst->addClause(handler.Type); } } done: - // If we have a catch-all, add null to the selector. + // If we have a catch-all, add null to the landingpad. assert(!(hasCatchAll && hasFilter)); if (hasCatchAll) { - selector.push_back(getCatchAllValue(*this)); + LPadInst->addClause(getCatchAllValue(*this)); // If we have an EH filter, we need to add those handlers in the - // right place in the selector, which is to say, at the end. + // right place in the landingpad, which is to say, at the end. } else if (hasFilter) { // Create a filter expression: an integer constant saying how many // filters there are (+1 to avoid ambiguity with 0 for cleanup), // followed by the filter types. The personality routine only // lands here if the filter doesn't match. - selector.push_back(Builder.getInt32(filterTypes.size() + 1)); - selector.append(filterTypes.begin(), filterTypes.end()); + llvm::SmallVector Filters; + llvm::ArrayType *AType = + llvm::ArrayType::get(!filterTypes.empty() ? + filterTypes[0]->getType() : Int8PtrTy, + filterTypes.size()); + + for (unsigned i = 0, e = filterTypes.size(); i != e; ++i) + Filters.push_back(cast(filterTypes[i])); + llvm::Constant *FilterArray = llvm::ConstantArray::get(AType, Filters); + LPadInst->addClause(FilterArray); // Also check whether we need a cleanup. - if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup) - selector.push_back(CleanupHackLevel == CHL_MandatoryCatchall - ? getCatchAllValue(*this) - : getCleanupValue(*this)); + if (hasCleanup) + LPadInst->setCleanup(true); // Otherwise, signal that we at least have cleanups. } else if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup) { - selector.push_back(CleanupHackLevel == CHL_MandatoryCatchall - ? getCatchAllValue(*this) - : getCleanupValue(*this)); + if (CleanupHackLevel == CHL_MandatoryCatchall) + LPadInst->addClause(getCatchAllValue(*this)); + else + LPadInst->setCleanup(true); } - assert(selector.size() >= 3 && "selector call has only two arguments!"); + assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) && + "landingpad instruction has no clauses!"); // Tell the backend how to generate the landing pad. - llvm::CallInst *selectorCall = - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector), - selector, "eh.selector"); - selectorCall->setDoesNotThrow(); - - // Save the selector and exception pointer. - Builder.CreateStore(exn, getExceptionSlot()); - Builder.CreateStore(selectorCall, getEHSelectorSlot()); - Builder.CreateBr(getEHDispatchBlock(EHStack.getInnermostEHScope())); // Restore the old IR generation state. @@ -1462,19 +1456,11 @@ llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() { Builder.SetInsertPoint(TerminateLandingPad); // Tell the backend that this is a landing pad. - llvm::CallInst *Exn = - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn"); - Exn->setDoesNotThrow(); - const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions()); - - // Tell the backend what the exception table should be: - // nothing but a catch-all. - llvm::Value *Args[3] = { Exn, getOpaquePersonalityFn(CGM, Personality), - getCatchAllValue(*this) }; - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector), - Args, "eh.selector") - ->setDoesNotThrow(); + llvm::LandingPadInst *LPadInst = + Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL), + getOpaquePersonalityFn(CGM, Personality), 0); + LPadInst->addClause(getCatchAllValue(*this)); llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this)); TerminateCall->setDoesNotReturn(); @@ -1538,12 +1524,21 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock() { ->setDoesNotReturn(); break; case CHL_MandatoryCleanup: { - // In mandatory-cleanup mode, we should use llvm.eh.resume. - llvm::Value *Selector = getSelectorFromSlot(); - Builder.CreateCall2(CGM.getIntrinsic(llvm::Intrinsic::eh_resume), - Exn, Selector) - ->setDoesNotReturn(); - break; + // In mandatory-cleanup mode, we should use 'resume'. + + // Recreate the landingpad's return value for the 'resume' instruction. + llvm::Value *Exn = getExceptionFromSlot(); + llvm::Value *Sel = getSelectorFromSlot(); + + llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), + Sel->getType(), NULL); + llvm::Value *LPadVal = llvm::UndefValue::get(LPadType); + LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val"); + LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val"); + + Builder.CreateResume(LPadVal); + Builder.restoreIP(SavedIP); + return EHResumeBlock; } case CHL_Ideal: // In an idealized mode where we don't have to worry about the diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index b4b2eb16ad..d38a9b0859 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -365,9 +365,12 @@ static void TryMarkNoThrow(llvm::Function *F) { for (llvm::Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) for (llvm::BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) - if (llvm::CallInst *Call = dyn_cast(&*BI)) + if (llvm::CallInst *Call = dyn_cast(&*BI)) { if (!Call->doesNotThrow()) return; + } else if (isa(&*BI)) { + return; + } F->setDoesNotThrow(true); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 177e647b4d..19541a9767 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -612,12 +612,12 @@ public: /// EHResumeBlock - Unified block containing a call to llvm.eh.resume. llvm::BasicBlock *EHResumeBlock; - /// The exception slot. All landing pads write the current - /// exception pointer into this alloca. + /// The exception slot. All landing pads write the current exception pointer + /// into this alloca. llvm::Value *ExceptionSlot; - /// The selector slot. Under the MandatoryCleanup model, all - /// landing pads write the current selector value into this alloca. + /// The selector slot. Under the MandatoryCleanup model, all landing pads + /// write the current selector value into this alloca. llvm::AllocaInst *EHSelectorSlot; /// Emits a landing pad for the current EH stack. @@ -1116,8 +1116,8 @@ public: const LangOptions &getLangOptions() const { return CGM.getLangOptions(); } - /// Returns a pointer to the function's exception object slot, which - /// is assigned in every landing pad. + /// Returns a pointer to the function's exception object and selector slot, + /// which is assigned in every landing pad. llvm::Value *getExceptionSlot(); llvm::Value *getEHSelectorSlot(); diff --git a/test/CXX/except/except.spec/p9-dynamic.cpp b/test/CXX/except/except.spec/p9-dynamic.cpp index 3f496f25c9..4559e0d467 100644 --- a/test/CXX/except/except.spec/p9-dynamic.cpp +++ b/test/CXX/except/except.spec/p9-dynamic.cpp @@ -7,5 +7,6 @@ void target() throw(int) // CHECK: invoke void @_Z8externalv() external(); } -// CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} i8* bitcast (i8** @_ZTIi to i8*)) nounwind -// CHECK: call void @__cxa_call_unexpected +// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +// CHECK-NEXT: filter [1 x i8*] [i8* bitcast (i8** @_ZTIi to i8*)] +// CHECK: call void @__cxa_call_unexpected diff --git a/test/CXX/except/except.spec/p9-noexcept.cpp b/test/CXX/except/except.spec/p9-noexcept.cpp index 76ac66c841..7b2a259e19 100644 --- a/test/CXX/except/except.spec/p9-noexcept.cpp +++ b/test/CXX/except/except.spec/p9-noexcept.cpp @@ -7,7 +7,8 @@ void target() noexcept // CHECK: invoke void @_Z8externalv() external(); } -// CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} i8* null) nounwind +// CHECK: 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: unreachable diff --git a/test/CodeGen/exceptions.c b/test/CodeGen/exceptions.c index 018b975395..20eb706a03 100644 --- a/test/CodeGen/exceptions.c +++ b/test/CodeGen/exceptions.c @@ -14,6 +14,8 @@ void test1() { // CHECK-ARM: invoke arm_aapcscc void @test1_helper( test1_helper(^(int v) { x = v; }); - // CHECK: call {{.*}} @llvm.eh.selector({{.*}}, i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) - // CHECK-ARM: call {{.*}} @llvm.eh.selector({{.*}}, i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) + // CHECK-NEXT: cleanup + // CHECK-ARM: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*) + // CHECK-ARM-NEXT: cleanup } diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index dcb27ce0da..a767f42555 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -308,9 +308,10 @@ namespace test7 { // CHECK: ret void static int x = foo(); - // CHECK: call i8* @llvm.eh.exception() + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: call void @__cxa_guard_abort(i32* @_ZGVZN5test74testEvE1x) - // CHECK: call void @llvm.eh.resume( + // CHECK: resume { i8*, i32 } } } @@ -347,9 +348,10 @@ namespace test8 { // CHECK: ret void static A x; - // CHECK: call i8* @llvm.eh.exception() + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: call void @__cxa_guard_abort(i32* @_ZGVZN5test84testEvE1x) - // CHECK: call void @llvm.eh.resume( + // CHECK: resume { i8*, i32 } } } diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index dc24551a59..d9962e615e 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -356,9 +356,10 @@ namespace test8 { // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev( // CHECK: call void @_ZdlPv({{.*}}) nounwind // CHECK: ret void - // CHECK: call i8* @llvm.eh.exception( + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: call void @_ZdlPv({{.*}}) nounwind - // CHECK: call void @llvm.eh.resume( + // CHECK: resume { i8*, i32 } // Checked at top of file: // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev @@ -386,9 +387,10 @@ namespace test8 { // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD1Ev( // CHECK: call void @_ZdlPv({{.*}}) nounwind // CHECK: ret void - // CHECK: call i8* @llvm.eh.exception() + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: call void @_ZdlPv({{.*}}) nounwind - // CHECK: call void @llvm.eh.resume( + // CHECK: resume { i8*, i32 } // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev( // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8 diff --git a/test/CodeGenCXX/dynamic-cast.cpp b/test/CodeGenCXX/dynamic-cast.cpp index e84bb9b4ff..813e36e941 100644 --- a/test/CodeGenCXX/dynamic-cast.cpp +++ b/test/CodeGenCXX/dynamic-cast.cpp @@ -11,7 +11,8 @@ const B& f(A *a) { // CHECK: invoke void @__cxa_bad_cast() noreturn dynamic_cast(*a); } catch (...) { - // CHECK: call i8* @llvm.eh.exception + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: catch i8* null } return fail; } diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index 24807d92d7..e990994247 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -115,9 +115,12 @@ namespace test7 { throw 1; } -// CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception() -// CHECK-NEXT: [[SELECTOR:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null) +// CHECK: [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +// CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) +// CHECK-NEXT: catch i8* null +// CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 0 // CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]] +// CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 1 // CHECK-NEXT: store i32 [[SELECTOR]], i32* [[SELECTORVAR]] // CHECK-NEXT: br label // CHECK: [[SELECTOR:%.*]] = load i32* [[SELECTORVAR]] @@ -134,9 +137,11 @@ namespace test7 { throw; } } -// CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception() -// CHECK-NEXT: [[SELECTOR:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) +// CHECK: [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +// CHECK-NEXT: catch i8* null +// CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 0 // CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]] +// CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 1 // CHECK-NEXT: store i32 [[SELECTOR]], i32* [[SELECTORVAR]] // CHECK-NEXT: call void @__cxa_end_catch() // CHECK-NEXT: br label @@ -188,8 +193,8 @@ namespace test9 { // CHECK: invoke void @_ZN5test96opaqueEv() opaque(); } catch (int x) { - // CHECK: call i8* @llvm.eh.exception - // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*)) + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) // CHECK: call i8* @__cxa_begin_catch // CHECK: invoke void @_ZN5test96opaqueEv() diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 0efb355380..57bf27ab7a 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -68,8 +68,10 @@ X test2(bool B) { // -> %cleanup, %lpad1 // %lpad: landing pad for ctor of 'y', dtor of 'y' - // CHECK-EH: call i8* @llvm.eh.exception() - // CHECK-EH: call i32 (i8*, i8*, ...)* @llvm.eh.selector + // CHECK-EH: [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-EH-NEXT: cleanup + // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0 + // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1 // CHECK-EH-NEXT: br label // -> %eh.cleanup @@ -95,12 +97,11 @@ X test2(bool B) { // %invoke.cont17: rethrow block for %eh.cleanup. // This really should be elsewhere in the function. - // CHECK-EH: call void @llvm.eh.resume( - // CHECK-EH-NEXT: unreachable + // CHECK-EH: resume { i8*, i32 } // %terminate.lpad: terminate landing pad. - // CHECK-EH: call i8* @llvm.eh.exception() - // CHECK-EH-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector + // CHECK-EH: 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: unreachable diff --git a/test/CodeGenCXX/partial-destruction.cpp b/test/CodeGenCXX/partial-destruction.cpp index b28c1384b8..f232a159ed 100644 --- a/test/CodeGenCXX/partial-destruction.cpp +++ b/test/CodeGenCXX/partial-destruction.cpp @@ -50,7 +50,8 @@ namespace test0 { // CHECK: ret void // Partial destroy for initialization. - // CHECK: llvm.eh.selector({{.*}}, i32 0) + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: [[PARTIAL_END:%.*]] = load [[A]]** [[ENDVAR]] // CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[E_BEGIN]], [[PARTIAL_END]] // CHECK-NEXT: br i1 [[T0]], @@ -61,7 +62,8 @@ namespace test0 { // CHECK-NEXT: br i1 [[T0]], // Primary EH destructor. - // CHECK: llvm.eh.selector({{.*}}, i32 0) + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: [[E0:%.*]] = getelementptr inbounds [10 x [[A]]]* [[AS]], i32 0, i32 0 // CHECK-NEXT: [[E_END:%.*]] = getelementptr inbounds [[A]]* [[E0]], i64 10 // CHECK-NEXT: br label @@ -70,7 +72,8 @@ namespace test0 { // FIXME: There's some really bad block ordering here which causes // the partial destroy for the primary normal destructor to fall // within the primary EH destructor. - // CHECK: llvm.eh.selector({{.*}}, i32 0) + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ED_BEGIN]], [[ED_CUR]] // CHECK-NEXT: br i1 [[T0]] // CHECK: [[EDD_AFTER:%.*]] = phi [[A]]* [ [[ED_CUR]], {{%.*}} ], [ [[EDD_CUR:%.*]], {{%.*}} ] @@ -111,8 +114,10 @@ namespace test1 { // CHECK-NEXT: ret void // FIXME: again, the block ordering is pretty bad here - // CHECK: eh.selector({{.*}}, i32 0) - // CHECK: eh.selector({{.*}}, i32 0) + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[Y]]) // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[X]]) } @@ -139,7 +144,8 @@ namespace test2 { // CHECK-NEXT: br i1 [[DONE]], // Partial destruction landing pad. - // CHECK: llvm.eh.exception() + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: cleanup // CHECK: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[CUR]] // CHECK-NEXT: br i1 [[EMPTY]], // CHECK: [[PAST:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[DEL:%.*]], {{%.*}} ] diff --git a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp index aa79a4f6dd..769d120be3 100644 --- a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp +++ b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp @@ -21,9 +21,8 @@ void f() { throw Y(); // Finally, the landing pad. - // CHECK: call i8* @llvm.eh.exception() - // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK: cleanup // CHECK: call void @__cxa_guard_abort(i64* @_ZGVZ1fvE1x) - // CHECK: call void @llvm.eh.resume( - // CHECK: unreachable + // CHECK: resume { i8*, i32 } } diff --git a/test/CodeGenCXX/typeid.cpp b/test/CodeGenCXX/typeid.cpp index 1af96705ba..7ebf41c09f 100644 --- a/test/CodeGenCXX/typeid.cpp +++ b/test/CodeGenCXX/typeid.cpp @@ -13,7 +13,8 @@ const char *f() { // CHECK: invoke void @__cxa_bad_typeid() noreturn return typeid(*static_cast(0)).name(); } catch (...) { - // CHECK: call i8* @llvm.eh.exception + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: catch i8* null } return 0; diff --git a/test/CodeGenObjC/blocks-2.m b/test/CodeGenObjC/blocks-2.m index 5d63e919fb..56eb8a7779 100644 --- a/test/CodeGenObjC/blocks-2.m +++ b/test/CodeGenObjC/blocks-2.m @@ -30,8 +30,9 @@ void test1() { // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) // CHECK-NEXT: ret void - // CHECK: call i8* @llvm.eh.exception() + // CHECK: landingpad { i8*, i32 } personality + // CHECK-NEXT: cleanup // CHECK: [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8* // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) - // CHECK: call void @llvm.eh.resume( + // CHECK: resume { i8*, i32 } } diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m index 7f3ae9df46..8917bf3120 100644 --- a/test/CodeGenObjC/gnu-exceptions.m +++ b/test/CodeGenObjC/gnu-exceptions.m @@ -14,9 +14,9 @@ void test0() { // CHECK: call void @log(i32 1) } @catch (C *c) { - // CHECK: call i8* @llvm.eh.exception() - // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gnu_objc_personality_v0 - // CHECK: br i1 + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*) + // CHECK-NEXT: catch i8* getelementptr inbounds ([2 x i8]* @0, i64 0, i64 0) + // CHECK: br i1 // CHECK: call void @log(i32 0) diff --git a/test/CodeGenObjC/terminate.m b/test/CodeGenObjC/terminate.m index f04eb6a92b..0e01d89086 100644 --- a/test/CodeGenObjC/terminate.m +++ b/test/CodeGenObjC/terminate.m @@ -14,8 +14,8 @@ void test0(void) { // CHECK-WITH: call void @destroy(i8** [[PTR]]) // CHECK-WITH-NEXT: ret void // CHECK-WITH: invoke void @destroy(i8** [[PTR]]) - // CHECK-WITH: call i8* @llvm.eh.exception() - // CHECK-WITH-NEXT: @llvm.eh.selector + // CHECK-WITH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) + // CHECK-WITH-NEXT: catch i8* null // CHECK-WITH-NEXT: call void @objc_terminate() // CHECK-WITHOUT: define void @test0() @@ -23,7 +23,7 @@ void test0(void) { // CHECK-WITHOUT: call void @destroy(i8** [[PTR]]) // CHECK-WITHOUT-NEXT: ret void // CHECK-WITHOUT: invoke void @destroy(i8** [[PTR]]) - // CHECK-WITHOUT: call i8* @llvm.eh.exception() - // CHECK-WITHOUT-NEXT: @llvm.eh.selector + // CHECK-WITHOUT: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) + // CHECK-WITHOUT-NEXT: catch i8* null // CHECK-WITHOUT-NEXT: call void @abort() } diff --git a/test/CodeGenObjCXX/catch-id-type.mm b/test/CodeGenObjCXX/catch-id-type.mm index ece342bb87..b3f99b4fdd 100644 --- a/test/CodeGenObjCXX/catch-id-type.mm +++ b/test/CodeGenObjCXX/catch-id-type.mm @@ -30,7 +30,10 @@ id FUNC() { } catch( id error ) { - // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gxx_personality_v0 {{.*}} @_ZTIP4INTF {{.*}} @_ZTIP11objc_object {{.*}} @_ZTIP10objc_class + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP4INTF to i8*) + // CHECK-NEXT: catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP11objc_object to i8*) + // CHECK-NEXT: catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP10objc_class to i8*) error = error; groups = [ns_array array]; } diff --git a/test/CodeGenObjCXX/exceptions.mm b/test/CodeGenObjCXX/exceptions.mm index d4c0756cb8..9f092b9ac7 100644 --- a/test/CodeGenObjCXX/exceptions.mm +++ b/test/CodeGenObjCXX/exceptions.mm @@ -11,7 +11,8 @@ namespace test0 { // CHECK: invoke void @_Z6opaquev opaque(); } catch (OCType *T) { - // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__objc_personality_v0 {{.*}} @"OBJC_EHTYPE_$_OCType" + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) + // CHECK-NEXT: catch %struct._objc_typeinfo* @"OBJC_EHTYPE_$_OCType" } } } -- 2.40.0