Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -15,6 +15,7 @@ #include "CGCall.h" #include "ABIInfo.h" #include "CGCXXABI.h" +#include "CGCleanup.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "TargetInfo.h" @@ -3472,11 +3473,22 @@ llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), AttributeList); - llvm::BasicBlock *InvokeDest = nullptr; - if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex, - llvm::Attribute::NoUnwind) || - currentFunctionUsesSEHTry()) - InvokeDest = getInvokeDest(); + bool CannotThrow; + if (currentFunctionUsesSEHTry()) { + // SEH cares about asynchronous exceptions, everything can "throw." + CannotThrow = false; + } else if (isCleanupPadScope() && + &EHPersonality::get(*this) == + &EHPersonality::MSVC_CxxFrameHandler3) { + // The MSVC++ personality will implicitly terminate the program if an + // exception is thrown. An unwind edge cannot be reached. + CannotThrow = true; + } else { + // Otherwise, nowunind callsites will never throw. + CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoUnwind); + } + llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); llvm::CallSite CS; if (!InvokeDest) { @@ -3495,14 +3507,8 @@ Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, llvm::Attribute::AlwaysInline); - // Disable inlining inside SEH __try blocks and cleanup funclets. None of the - // funclet EH personalities that clang supports have tables that are - // expressive enough to describe catching an exception inside a cleanup. - // __CxxFrameHandler3, for example, will terminate the program without - // catching it. - // FIXME: Move this decision to the LLVM inliner. Before we can do that, the - // inliner needs to know if a given call site is part of a cleanuppad. - if (isSEHTryScope() || isCleanupPadScope()) + // Disable inlining inside SEH __try blocks. + if (isSEHTryScope()) Attrs = Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoInline); Index: lib/CodeGen/CGCleanup.h =================================================================== --- lib/CodeGen/CGCleanup.h +++ lib/CodeGen/CGCleanup.h @@ -587,14 +587,6 @@ deallocate(EHTerminateScope::getSize()); } -inline void EHScopeStack::popPadEnd() { - assert(!empty() && "popping exception stack when not empty"); - - EHPadEndScope &scope = cast(*begin()); - InnermostEHScope = scope.getEnclosingEHScope(); - deallocate(EHPadEndScope::getSize()); -} - inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const { assert(sp.isValid() && "finding invalid savepoint"); assert(sp.Size <= stable_begin().Size && "finding savepoint after pop"); Index: lib/CodeGen/CGCleanup.cpp =================================================================== --- lib/CodeGen/CGCleanup.cpp +++ lib/CodeGen/CGCleanup.cpp @@ -246,13 +246,6 @@ InnermostEHScope = stable_begin(); } -void EHScopeStack::pushPadEnd(llvm::BasicBlock *PadEndBB) { - char *Buffer = allocate(EHPadEndScope::getSize()); - auto *CES = new (Buffer) EHPadEndScope(InnermostEHScope); - CES->setCachedEHDispatchBlock(PadEndBB); - InnermostEHScope = stable_begin(); -} - /// Remove any 'null' fixups on the stack. However, we can't pop more /// fixups than the fixup depth on the innermost normal cleanup, or /// else fixups that we try to add to that cleanup will end up in the @@ -909,24 +902,17 @@ // throwing cleanups. For funclet EH personalities, the cleanupendpad models // program termination when cleanups throw. bool PushedTerminate = false; - SaveAndRestore RestoreIsCleanupPadScope(IsCleanupPadScope); + SaveAndRestore RestoreCurrentFuncletPad( + CurrentFuncletPad); llvm::CleanupPadInst *CPI = nullptr; - llvm::BasicBlock *CleanupEndBB = nullptr; if (!EHPersonality::get(*this).usesFuncletPads()) { EHStack.pushTerminate(); PushedTerminate = true; } else { - CPI = Builder.CreateCleanupPad({}); - - // Build a cleanupendpad to unwind through. Our insertion point should be - // in the cleanuppad block. - CleanupEndBB = createBasicBlock("ehcleanup.end"); - CGBuilderTy(*this, CleanupEndBB).CreateCleanupEndPad(CPI, NextAction); - EHStack.pushPadEnd(CleanupEndBB); - - // Mark that we're inside a cleanuppad to block inlining. - // FIXME: Remove this once the inliner knows when it's safe to do so. - IsCleanupPadScope = true; + llvm::Value *OuterScope = CurrentFuncletPad; + if (!OuterScope) + OuterScope = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); + CurrentFuncletPad = CPI = Builder.CreateCleanupPad(OuterScope); } // We only actually emit the cleanup code if the cleanup is either @@ -941,17 +927,6 @@ else Builder.CreateBr(NextAction); - // Insert the cleanupendpad block here, if it has any uses. - if (CleanupEndBB) { - EHStack.popPadEnd(); - if (CleanupEndBB->hasNUsesOrMore(1)) { - CurFn->getBasicBlockList().insertAfter( - Builder.GetInsertBlock()->getIterator(), CleanupEndBB); - } else { - delete CleanupEndBB; - } - } - // Leave the terminate scope. if (PushedTerminate) EHStack.popTerminate(); Index: lib/CodeGen/CGException.cpp =================================================================== --- lib/CodeGen/CGException.cpp +++ lib/CodeGen/CGException.cpp @@ -871,58 +871,53 @@ return lpad; } -static llvm::BasicBlock *emitCatchPadBlock(CodeGenFunction &CGF, - EHCatchScope &CatchScope) { +static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope) { llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock(); assert(DispatchBlock); CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP(); CGF.EmitBlockAfterUses(DispatchBlock); - // Figure out the next block. - llvm::BasicBlock *NextBlock = nullptr; + llvm::Value *OuterScope = CGF.CurrentFuncletPad; + if (!OuterScope) + OuterScope = llvm::ConstantTokenNone::get(CGF.getLLVMContext()); + llvm::BasicBlock *UnwindBB = + CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()); + + unsigned NumHandlers = CatchScope.getNumHandlers(); + llvm::CatchSwitchInst *CatchSwitch = + CGF.Builder.CreateCatchSwitch(OuterScope, UnwindBB, NumHandlers); // Test against each of the exception types we claim to catch. - for (unsigned I = 0, E = CatchScope.getNumHandlers(); I < E; ++I) { + for (unsigned I = 0; I < NumHandlers; ++I) { const EHCatchScope::Handler &Handler = CatchScope.getHandler(I); CatchTypeInfo TypeInfo = Handler.Type; if (!TypeInfo.RTTI) TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy); - // If this is the last handler, we're at the end, and the next - // block is the block for the enclosing EH scope. - if (I + 1 == E) { - NextBlock = CGF.createBasicBlock("catchendblock"); - CGBuilderTy(CGF, NextBlock).CreateCatchEndPad( - CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope())); - } else { - NextBlock = CGF.createBasicBlock("catch.dispatch"); - } + llvm::BasicBlock *CatchPadBB = CGF.createBasicBlock("catch"); + CGF.EmitBlock(CatchPadBB); if (EHPersonality::get(CGF).isMSVCXXPersonality()) { - CGF.Builder.CreateCatchPad(Handler.Block, NextBlock, - {TypeInfo.RTTI, - CGF.Builder.getInt32(TypeInfo.Flags), - llvm::Constant::getNullValue(CGF.VoidPtrTy)}); + CGF.Builder.CreateCatchPad( + CatchSwitch, {TypeInfo.RTTI, CGF.Builder.getInt32(TypeInfo.Flags), + llvm::Constant::getNullValue(CGF.VoidPtrTy)}); } else { - CGF.Builder.CreateCatchPad(Handler.Block, NextBlock, {TypeInfo.RTTI}); + CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI}); } - // Otherwise we need to emit and continue at that block. - CGF.EmitBlock(NextBlock); + CGF.Builder.CreateBr(Handler.Block); + + CatchSwitch->addHandler(CatchPadBB); } CGF.Builder.restoreIP(SavedIP); - - return NextBlock; } /// Emit the structure of the dispatch block for the given catch scope. /// It is an invariant that the dispatch block already exists. -/// If the catchblock instructions are used for EH dispatch, then the basic -/// block holding the final catchendblock instruction is returned. -static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF, - EHCatchScope &catchScope) { +static void emitCatchDispatchBlock(CodeGenFunction &CGF, + EHCatchScope &catchScope) { if (EHPersonality::get(CGF).usesFuncletPads()) return emitCatchPadBlock(CGF, catchScope); @@ -934,7 +929,7 @@ if (catchScope.getNumHandlers() == 1 && catchScope.getHandler(0).isCatchAll()) { assert(dispatchBlock == catchScope.getHandler(0).Block); - return nullptr; + return; } CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP(); @@ -992,12 +987,11 @@ // If the next handler is a catch-all, we're completely done. if (nextIsEnd) { CGF.Builder.restoreIP(savedIP); - return nullptr; + return; } // Otherwise we need to emit and continue at that block. CGF.EmitBlock(nextBlock); } - return nullptr; } void CodeGenFunction::popCatchScope() { @@ -1020,7 +1014,7 @@ } // Emit the structure of the EH dispatch for this catch. - llvm::BasicBlock *CatchEndBlockBB = emitCatchDispatchBlock(*this, CatchScope); + emitCatchDispatchBlock(*this, CatchScope); // Copy the handler blocks off before we pop the EH stack. Emitting // the handlers might scribble on this memory. @@ -1043,9 +1037,6 @@ doImplicitRethrow = isa(CurCodeDecl) || isa(CurCodeDecl); - if (CatchEndBlockBB) - EHStack.pushPadEnd(CatchEndBlockBB); - // Perversely, we emit the handlers backwards precisely because we // want them to appear in source order. In all of these cases, the // catch block will have exactly one predecessor, which will be a @@ -1065,6 +1056,8 @@ RunCleanupsScope CatchScope(*this); // Initialize the catch variable and set up the cleanups. + SaveAndRestore RestoreCurrentFuncletPad( + CurrentFuncletPad); CGM.getCXXABI().emitBeginCatch(*this, C); // Emit the PGO counter increment. @@ -1098,8 +1091,6 @@ EmitBlock(ContBB); incrementProfileCounter(&S); - if (CatchEndBlockBB) - EHStack.popPadEnd(); } namespace { @@ -1338,7 +1329,11 @@ TerminateHandler = createBasicBlock("terminate.handler"); Builder.SetInsertPoint(TerminateHandler); if (EHPersonality::get(*this).usesFuncletPads()) { - Builder.CreateTerminatePad(/*UnwindBB=*/nullptr, CGM.getTerminateFn()); + llvm::Value *OuterScope = CurrentFuncletPad; + if (!OuterScope) + OuterScope = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); + Builder.CreateTerminatePad(OuterScope, /*UnwindBB=*/nullptr, + {CGM.getTerminateFn()}); } else { llvm::Value *Exn = nullptr; if (getLangOpts().CPlusPlus) Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -279,8 +279,6 @@ /// finally block or filter expression. bool IsOutlinedSEHHelper; - bool IsCleanupPadScope = false; - const CodeGen::CGBlockInfo *BlockInfo; llvm::Value *BlockPointer; @@ -295,6 +293,8 @@ llvm::SmallVector LifetimeExtendedCleanupStack; llvm::SmallVector SEHTryEpilogueStack; + llvm::Instruction *CurrentFuncletPad = nullptr; + /// Header for data within LifetimeExtendedCleanupStack. struct LifetimeExtendedCleanupHeader { /// The size of the following cleanup object. @@ -375,7 +375,9 @@ bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); } /// Returns true while emitting a cleanuppad. - bool isCleanupPadScope() const { return IsCleanupPadScope; } + bool isCleanupPadScope() const { + return CurrentFuncletPad && isa(CurrentFuncletPad); + } /// pushFullExprCleanup - Push a cleanup to be run at the end of the /// current full-expression. Safe against the possibility that Index: lib/CodeGen/EHScopeStack.h =================================================================== --- lib/CodeGen/EHScopeStack.h +++ lib/CodeGen/EHScopeStack.h @@ -334,10 +334,6 @@ /// Pops a terminate handler off the stack. void popTerminate(); - void pushPadEnd(llvm::BasicBlock *PadEndBB); - - void popPadEnd(); - // Returns true iff the current scope is either empty or contains only // lifetime markers, i.e. no real cleanup code bool containsOnlyLifetimeMarkers(stable_iterator Old) const; Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -897,6 +897,7 @@ CGF.Builder.GetInsertBlock()->getSinglePredecessor(); llvm::CatchPadInst *CPI = cast(CatchPadBB->getFirstNonPHI()); + CGF.CurrentFuncletPad = CPI; // If this is a catch-all or the catch parameter is unnamed, we don't need to // emit an alloca to the object. Index: test/CodeGen/exceptions-seh-finally.c =================================================================== --- test/CodeGen/exceptions-seh-finally.c +++ test/CodeGen/exceptions-seh-finally.c @@ -25,12 +25,8 @@ // CHECK: [[lpad]] // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() -// CHECK: invoke void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) -// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]] -// CHECK: cleanupret %[[pad]] unwind to caller -// -// CHECK: [[end]] -// CHECK: cleanupendpad %[[pad]] unwind to caller +// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) +// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}}) // CHECK: call void @cleanup() @@ -95,12 +91,8 @@ // CHECK: [[lpad]] // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() -// CHECK: invoke void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) -// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]] -// CHECK: cleanupret %[[pad]] unwind to caller -// -// CHECK: [[end]] -// CHECK: cleanupendpad %[[pad]] unwind to caller +// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) +// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer) // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32 @@ -141,12 +133,8 @@ // // CHECK: [[lpad]] // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad -// CHECK: invoke void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) -// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]] -// CHECK: cleanupret %[[pad]] unwind to caller -// -// CHECK: [[end]] -// CHECK: cleanupendpad %[[pad]] unwind to caller +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) +// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) // CHECK: call void @abort() @@ -189,12 +177,8 @@ // // CHECK: [[lpad]] // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad -// CHECK: invoke void @"\01?fin$0@0@nested___finally___finally@@"({{.*}}) -// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]] -// CHECK: cleanupret %[[pad]] unwind to caller -// -// CHECK: [[end]] -// CHECK: cleanupendpad %[[pad]] unwind to caller +// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}}) +// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}}) // CHECK: ret void @@ -231,24 +215,15 @@ // CHECK: [[lpad1]] // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) -// CHECK-NEXT: to label %[[innercleanupretbb:[^ ]*]] unwind label %[[innerend:[^ ]*]] +// CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]] // // CHECK: [[innercleanupretbb]] -// CHECK-NEXT: cleanupret %[[innerpad]] unwind label %[[lpad2]] -// -// CHECK: [[innerend]] -// CHECK-NEXT: cleanupendpad %[[innerpad]] unwind label %[[lpad2:[^ ]*]] +// CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]] // // CHECK: [[lpad2]] // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad -// CHECK: invoke void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) -// CHECK-NEXT: to label %[[outercleanupretbb:[^ ]*]] unwind label %[[outerend:[^ ]*]] -// -// CHECK: [[outercleanupretbb]] -// CHECK-NEXT: cleanupret %[[outerpad]] unwind to caller -// -// CHECK: [[outerend]] -// CHECK-NEXT: cleanupendpad %[[outerpad]] unwind to caller +// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) +// CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) // CHECK: ret void Index: test/CodeGen/exceptions-seh-leave.c =================================================================== --- test/CodeGen/exceptions-seh-leave.c +++ test/CodeGen/exceptions-seh-leave.c @@ -160,20 +160,17 @@ // CHECK-NEXT: cleanuppad // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() // CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]]) -// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[cleanupend:[^ ]*]] +// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]] // CHECK: cleanupret {{.*}} unwind label %[[g2_lpad]] // CHECK: [[g2_lpad]] -// CHECK: catchpad [i8* null] +// CHECK: catchpad {{.*}} [i8* null] // CHECK: catchret // CHECK: br label %[[trycont]] // CHECK: [[trycont]] // CHECK-NEXT: ret i32 1 -// CHECK: [[cleanupend]] -// CHECK-NEXT: cleanupendpad {{.*}} unwind label %[[g2_lpad]] - // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: call void @g() // CHECK: unreachable @@ -203,14 +200,14 @@ // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] // CHECK: [[g1_lpad]] -// CHECK: catchpad [i8* null] +// CHECK: catchpad {{.*}} [i8* null] // CHECK: catchret {{.*}} to label %[[except:[^ ]*]] // CHECK: [[except]] // CHECK: invoke void @g() // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] // CHECK: [[g2_lpad]] -// CHECK: catchpad [i8* null] +// CHECK: catchpad {{.*}} [i8* null] // CHECK: catchret // CHECK: br label %[[trycont4:[^ ]*]] @@ -280,7 +277,7 @@ // CHECK: [[g2_lpad]] // CHECK: cleanuppad // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() -// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]]) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]]) // CHECK: cleanupret {{.*}} unwind to caller // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer) @@ -323,21 +320,18 @@ // CHECK-NEXT: ret i32 1 // CHECK: [[g1_lpad]] -// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad [] +// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none [] // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() // CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]]) -// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[endcleanup:[^ ]*]] +// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]] // CHECK: [[finally_cont2]] -// CHECK: cleanupret %[[padtoken]] unwind label %[[g2_lpad]] - -// CHECK: [[endcleanup]] -// CHECK-NEXT: cleanupendpad %[[padtoken]] unwind label %[[g2_lpad]] +// CHECK: cleanupret from %[[padtoken]] unwind label %[[g2_lpad]] // CHECK: [[g2_lpad]] -// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad [] +// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad within none [] // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() -// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]]) -// CHECK: cleanupret %[[padtoken]] unwind to caller +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]]) +// CHECK: cleanupret from %[[padtoken]] unwind to caller // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: ret void Index: test/CodeGen/exceptions-seh.c =================================================================== --- test/CodeGen/exceptions-seh.c +++ test/CodeGen/exceptions-seh.c @@ -34,12 +34,12 @@ // CHECK: to label %{{.*}} unwind label %[[catchpad:[^ ]*]] // // CHECK: [[catchpad]] -// X64: %[[padtoken:[^ ]*]] = catchpad [i8* null] -// X86: %[[padtoken:[^ ]*]] = catchpad [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)] -// CHECK-NEXT: to label %[[exceptret:[^ ]*]] unwind label +// X64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null] +// X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)] +// CHECK-NEXT: br label %[[exceptret:[^ ]*]] // // CHECK: [[exceptret]] -// CHECK: catchret %[[padtoken]] to label %[[except:[^ ]*]] +// CHECK: catchret from %[[padtoken]] to label %[[except:[^ ]*]] // // CHECK: [[except]] // CHECK: store i32 -42, i32* %[[success:[^ ]*]] @@ -85,7 +85,7 @@ // CHECK: store i32 42, i32* %[[r]] // CHECK: invoke void @j() #[[NOINLINE]] // -// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)] +// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)] // CHECK: store i32 13, i32* %[[r]] // // CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]] @@ -121,37 +121,43 @@ // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) // CHECK: store i32 42, i32* %[[r:[^ ,]*]] // CHECK: invoke void @j() #[[NOINLINE]] -// CHECK: to label %[[cont:[^ ]*]] unwind label %[[cpad_inner:[^ ]*]] +// CHECK: to label %[[cont:[^ ]*]] unwind label %[[cswitch_inner:[^ ]*]] // -// CHECK: [[cpad_inner]] -// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)] -// CHECK-NEXT: to label %[[exceptret_inner:[^ ]*]] unwind label %[[cpad_outer:[^ ]*]] -// -// CHECK: [[exceptret_inner]] -// CHECK: catchret {{.*}} to label %[[except_inner:[^ ]*]] -// -// CHECK: [[except_inner]] -// CHECK: store i32 123, i32* %[[r]] -// CHECK: br label %[[inner_try_cont:[^ ]*]] +// CHECK: [[cswitch_inner]] +// CHECK: %[[cs_inner:[^ ]*]] = catchswitch within none, unwind label %[[cswitch_outer:[^ ]*]] [label %[[cpad_inner:[^ ]*]]] // -// CHECK: [[inner_try_cont]] -// CHECK: br label %[[outer_try_cont:[^ ]*]] +// CHECK: [[cswitch_outer]] +// CHECK: %[[cs_outer:[^ ]*]] = catchswitch within none, unwind to caller [label %[[cpad_outer:[^ ]*]]] // // CHECK: [[cpad_outer]] -// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)] -// CHECK-NEXT: to label %[[exceptret_outer:[^ ]*]] unwind label +// CHECK: catchpad within %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)] +// CHECK-NEXT: br label %[[exceptret_outer:[^ ]*]] // // CHECK: [[exceptret_outer]] // CHECK: catchret {{.*}} to label %[[except_outer:[^ ]*]] // // CHECK: [[except_outer]] // CHECK: store i32 456, i32* %[[r]] -// CHECK: br label %[[outer_try_cont]] +// CHECK: br label %[[outer_try_cont:[^ ]*]] // // CHECK: [[outer_try_cont]] // CHECK: %[[r_load:[^ ]*]] = load i32, i32* %[[r]] // CHECK: ret i32 %[[r_load]] // +// CHECK: [[cpad_inner]] +// CHECK: catchpad within %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)] +// CHECK-NEXT: br label %[[exceptret_inner:[^ ]*]] +// +// CHECK: [[exceptret_inner]] +// CHECK: catchret {{.*}} to label %[[except_inner:[^ ]*]] +// +// CHECK: [[except_inner]] +// CHECK: store i32 123, i32* %[[r]] +// CHECK: br label %[[inner_try_cont:[^ ]*]] +// +// CHECK: [[inner_try_cont]] +// CHECK: br label %[[outer_try_cont]] +// // CHECK: [[cont]] // CHECK: store i32 0, i32* %[[r]] // CHECK: br label %[[inner_try_cont]] @@ -193,14 +199,10 @@ // CHECK: ret i32 // // CHECK: [[cleanuppad]] -// CHECK: %[[padtoken:[^ ]*]] = cleanuppad [] +// CHECK: %[[padtoken:[^ ]*]] = cleanuppad within none [] // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() -// CHECK: invoke void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) -// CHECK: to label %[[cleanupcont:[^ ]*]] unwind label %[[cleanupend:[^ ]*]] -// CHECK: [[cleanupcont]] -// CHECK: cleanupret %[[padtoken]] unwind to caller -// CHECK: [[cleanupend]] -// CHECK: cleanupendpad %[[padtoken]] unwind to caller +// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) +// CHECK: cleanupret from %[[padtoken]] unwind to caller // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer) // CHECK: call i8* @llvm.localrecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0) @@ -278,7 +280,7 @@ // CHECK: %[[code_slot:[^ ]*]] = alloca i32 // CHECK: invoke void @try_body(i32 0, i32 0, i32* null) // CHECK: %[[pad:[^ ]*]] = catchpad -// CHECK: catchret %[[pad]] +// CHECK: catchret from %[[pad]] // X64: %[[code:[^ ]*]] = call i32 @llvm.eh.exceptioncode(token %[[pad]]) // X64: store i32 %[[code]], i32* %[[code_slot]] // CHECK: %[[ret1:[^ ]*]] = load i32, i32* %[[code_slot]] Index: test/CodeGenCXX/exceptions-cxx-new.cpp =================================================================== --- test/CodeGenCXX/exceptions-cxx-new.cpp +++ test/CodeGenCXX/exceptions-cxx-new.cpp @@ -14,18 +14,18 @@ // CHECK-LABEL: define void @"\01?test_catch@@YAXXZ"( // CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 1) -// CHECK: to label %[[NORMAL:.*]] unwind label %[[CATCH_INT:.*]] +// CHECK: to label %[[NORMAL:.*]] unwind label %[[CATCHSWITCH:.*]] + +// CHECK: [[CATCHSWITCH]] +// CHECK: %[[CATCHSWITCHPAD:.*]] = catchswitch within none, unwind to caller [label %[[CATCH_INT:.*]], label %[[CATCH_DOUBLE:.*]]] // CHECK: [[CATCH_INT]] -// CHECK: %[[CATCHPAD_INT:.*]] = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] -// CHECK: to label %[[CATCH_INT_HANDLER:.*]] unwind label %[[CATCH_DOUBLE:.*]] +// CHECK: %[[CATCHPAD_INT:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] +// CHECK: br label %[[CATCH_INT_HANDLER:.*]] // CHECK: [[CATCH_INT_HANDLER]] -// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 2) -// CHECK: to label %[[CATCH_INT_DONE:.*]] unwind label %[[CATCHENDPAD:.*]] - -// CHECK: [[CATCH_INT_DONE]] -// CHECK: catchret %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]] +// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 2) +// CHECK: catchret from %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]] // CHECK: [[LEAVE_INT_CATCH]] // CHECK: br label %[[LEAVE_FUNC:.*]] @@ -34,22 +34,16 @@ // CHECK: ret void // CHECK: [[CATCH_DOUBLE]] -// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null] -// CHECK: to label %[[CATCH_DOUBLE_HANDLER:.*]] unwind label %[[CATCHENDPAD]] +// CHECK: %[[CATCHPAD_DOUBLE:.*]] = catchpad within %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null] +// CHECK: br label %[[CATCH_DOUBLE_HANDLER:.*]] // CHECK: [[CATCH_DOUBLE_HANDLER]] -// CHECK: invoke i32 @"\01?f@@YAHH@Z"(i32 3) -// CHECK: to label %[[CATCH_DOUBLE_DONE:.*]] unwind label %[[CATCHENDPAD]] - -// CHECK: [[CATCH_DOUBLE_DONE]] -// CHECK: catchret %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]] +// CHECK: call i32 @"\01?f@@YAHH@Z"(i32 3) +// CHECK: catchret from %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]] // CHECK: [[LEAVE_DOUBLE_CATCH]] // CHECK: br label %[[LEAVE_FUNC]] -// CHECK: [[CATCHENDPAD]] -// CHECK: catchendpad unwind to caller - // CHECK: [[NORMAL]] // CHECK: br label %[[LEAVE_FUNC]] @@ -71,9 +65,9 @@ // CHECK: ret void // CHECK: [[CLEANUP]] -// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad [] +// CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none [] // CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"( -// CHECK: cleanupret %[[CLEANUPPAD]] unwind to caller +// CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller // CHECK-LABEL: define {{.*}} void @"\01??1Cleanup@@QAE@XZ"( @@ -84,5 +78,5 @@ // CHECK: ret void // CHECK: [[TERMINATE]] -// CHECK: terminatepad [void ()* @"\01?terminate@@YAXXZ"] unwind to caller +// CHECK: terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller Index: test/CodeGenCXX/exceptions-seh.cpp =================================================================== --- test/CodeGenCXX/exceptions-seh.cpp +++ test/CodeGenCXX/exceptions-seh.cpp @@ -61,7 +61,10 @@ // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[lpad]] -// CHECK-NEXT: catchpad +// CHECK-NEXT: %[[switch:.*]] = catchswitch within none, unwind to caller [label %[[cpad:.*]]] +// +// CHECK: [[cpad]] +// CHECK-NEXT: catchpad within %[[switch]] // CHECK: catchret {{.*}} label %[[except:[^ ]*]] // // CHECK: [[except]] @@ -119,7 +122,7 @@ // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK: invoke void @might_throw() // -// CHECK: catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)] +// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)] // // CHECK: invoke void @might_throw() // @@ -129,7 +132,7 @@ // // CHECK: cleanuppad // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() -// CHECK: invoke void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]]) +// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]]) // CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func) // CHECK: icmp eq i32 %{{.*}}, 424242 Index: test/CodeGenCXX/microsoft-abi-arg-order.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-arg-order.cpp +++ test/CodeGenCXX/microsoft-abi-arg-order.cpp @@ -52,7 +52,7 @@ // X86: ret void // // lpad2: -// X86: cleanuppad [] +// X86: cleanuppad within none [] // X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]]) // X86: cleanupret // @@ -68,7 +68,7 @@ // X64: ret void // // lpad2: -// X64: cleanuppad [] +// X64: cleanuppad within none [] // X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]]) // X64: cleanupret // Index: test/CodeGenCXX/microsoft-abi-eh-catch.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-eh-catch.cpp +++ test/CodeGenCXX/microsoft-abi-eh-catch.cpp @@ -19,15 +19,18 @@ // WIN64-LABEL: define void @catch_all() // WIN64: invoke void @might_throw() -// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] +// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[catchswitch_lpad:[^ ]*]] // -// WIN64: [[lpad]] -// WIN64: catchpad [i8* null, i32 64, i8* null] -// WIN64: to label %[[catchit:[^ ]*]] unwind label %{{.*}} +// WIN64: [[catchswitch_lpad]] +// WIN64: %[[catchswitch:[^ ]*]] = catchswitch within none, unwind to caller [label %[[catchpad_lpad:[^ ]*]]] +// +// WIN64: [[catchpad_lpad]] +// WIN64: catchpad within %[[catchswitch]] [i8* null, i32 64, i8* null] +// WIN64: br label %[[catchit:[^ ]*]] // // WIN64: [[catchit]] // WIN64: call void @recover() -// WIN64: catchret %{{.*}} to label %[[catchret:[^ ]*]] +// WIN64: catchret from %{{.*}} to label %[[catchret:[^ ]*]] // // WIN64: [[catchret]] // WIN64-NEXT: br label %[[ret:[^ ]*]] @@ -47,7 +50,7 @@ } // WIN64-LABEL: define void @catch_int() -// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]] +// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]] // // The catchpad instruction starts the lifetime of 'e'. Unfortunately, that // leaves us with nowhere to put lifetime.start, so we don't emit lifetime @@ -69,7 +72,7 @@ } // WIN64-LABEL: define void @catch_int_unnamed() -// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] +// WIN64: catchpad within %{{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] // WIN64: catchret struct A { @@ -96,7 +99,7 @@ // WIN64-LABEL: define void @catch_a_byval() // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A -// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]] +// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]] // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8* // WIN64: call void @handle_exception(i8* %[[e_i8]]) // WIN64: catchret @@ -111,7 +114,7 @@ // WIN64-LABEL: define void @catch_a_ref() // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A* -// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]] +// WIN64: catchpad within %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]] // WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]] // WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8* // WIN64: call void @handle_exception(i8* %[[eptr_i8]]) @@ -139,25 +142,28 @@ // WIN64-LABEL: define void @catch_nested() // WIN64: invoke void @might_throw() -// WIN64-NEXT: to label %{{.*}} unwind label %[[lp1:[^ ]*]] +// WIN64-NEXT: to label %{{.*}} unwind label %[[catchswitch_outer:[^ ]*]] +// +// WIN64: [[catchswitch_outer]] +// WIN64: %[[catchswitch_outer_scope:[^ ]*]] = catchswitch within none, unwind to caller [label %[[catch_int_outer:[^ ]*]]] // -// WIN64: [[lp1]] -// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] -// WIN64: to label %[[catchit:[^ ]*]] unwind label %{{.*}} +// WIN64: [[catch_int_outer]] +// WIN64: %[[catchpad:[^ ]*]] = catchpad within %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] +// WIN64: br label %[[catchit:[^ ]*]] // // WIN64: [[catchit]] // WIN64: invoke void @might_throw() -// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[lp2:[^ ]*]] +// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[catchswitch_inner:[^ ]*]] // -// WIN64: [[lp2]] -// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] -// WIN64: to label %[[catchit2:[^ ]*]] unwind label %[[endcatch2:[^ ]*]] +// WIN64: [[catchswitch_inner]] +// WIN64: %[[catchswitch_inner_scope:[^ ]*]] = catchswitch within %[[catchpad]], unwind to caller [label %[[catch_int_inner:[^ ]*]]] // -// WIN64: [[catchit2]] -// WIN64-NEXT: invoke void @might_throw() -// WIN64-NEXT: to label %[[catchret1:[^ ]*]] unwind label %[[endcatch2]] +// WIN64: [[catch_int_inner]] +// WIN64: catchpad within %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] +// WIN64: br label %[[catchit2:[^ ]*]] // -// WIN64: [[catchret1]] +// WIN64: [[catchit2]] +// WIN64-NEXT: call void @might_throw() // WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]] // // WIN64: [[catchret2]] @@ -165,6 +171,3 @@ // // WIN64: [[mainret]] // WIN64: ret void -// -// WIN64: [[endcatch2]] -// WIN64: catchendpad unwind label %{{.*}} Index: test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp +++ test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp @@ -27,7 +27,7 @@ // // There should be one dtor call for unwinding from the second getA. // WIN32: cleanuppad -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline:[0-9]+]] +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) // WIN32-NOT: @"\01??1A@@QAE@XZ" // WIN32: } @@ -62,7 +62,7 @@ // Conditionally destroy arg1. // WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]] // WIN32: br i1 %[[cond]] -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) #[[noinline]] +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) // WIN32: } // Test putting the cleanups inside a conditional. @@ -85,7 +85,7 @@ // WIN32: call i32 @"\01?CouldThrow@@YAHXZ"() // // Only one dtor in the invoke for arg1 -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]] +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) // WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" // WIN32: } @@ -126,7 +126,7 @@ // Somewhere in the landing pad soup, we conditionally destroy arg1. // WIN32: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] // WIN32: br i1 %[[isactive]] -// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]] +// WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) // WIN32: } namespace crash_on_partial_destroy { @@ -164,7 +164,7 @@ // WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4 // WIN32-NOT: load // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"* -// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}}) #[[noinline]] +// WIN32: call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}}) // WIN32: } } @@ -187,7 +187,7 @@ // // WIN32: [[lpad]] // WIN32-NEXT: cleanuppad -// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) #[[noinline]] +// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) } namespace noexcept_false_dtor { @@ -204,9 +204,5 @@ // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() // WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) // WIN32: cleanuppad -// WIN32: invoke x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) #[[invoke_noinline:[0-9]+]] +// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) // WIN32: cleanupret -// WIN32: cleanupendpad - -// WIN32: attributes #[[noinline]] = { noinline nounwind } -// WIN32: attributes #[[invoke_noinline]] = { noinline } Index: test/CodeGenCXX/microsoft-abi-eh-terminate.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-eh-terminate.cpp +++ test/CodeGenCXX/microsoft-abi-eh-terminate.cpp @@ -9,6 +9,6 @@ // CHECK-LABEL: define void @"\01?never_throws@@YAXXZ"() // CHECK-SAME: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) // CHECK: invoke void @"\01?may_throw@@YAXXZ"() -// MSVC2013: terminatepad [void ()* @"\01?terminate@@YAXXZ"] -// MSVC2015: terminatepad [void ()* @__std_terminate] +// MSVC2013: terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] +// MSVC2015: terminatepad within none [void ()* @__std_terminate] // CHECK-NEXT: unreachable Index: test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp +++ test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp @@ -39,7 +39,7 @@ // CHECK-NEXT: ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" // CHECK: [[lpad:.*]]: -// CHECK-NEXT: cleanuppad [] +// CHECK-NEXT: cleanuppad within none [] // CHECK: %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51" // CHECK-NEXT: %[[mask:.*]] = and i32 %[[guard]], -2 // CHECK-NEXT: store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51" @@ -75,7 +75,7 @@ // CHECK-NEXT: ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" // // CHECK: [[lpad]]: -// CHECK-NEXT: cleanuppad [] +// CHECK-NEXT: cleanuppad within none [] // CHECK: call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ") // CHECK-NEXT: cleanupret {{.*}} unwind to caller return s; Index: test/CodeGenCXX/microsoft-abi-try-throw.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-try-throw.cpp +++ test/CodeGenCXX/microsoft-abi-try-throw.cpp @@ -19,7 +19,7 @@ external(); // TRY: invoke void @"\01?external@@YAXXZ" } catch (int) { rv = 1; - // TRY: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] + // TRY: catchpad within %0 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] // TRY: catchret } #endif @@ -39,7 +39,7 @@ external(); } catch (const int *) { } - // TRY: catchpad [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null] + // TRY: catchpad within %0 [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null] // TRY: catchret } #endif