diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -645,6 +645,7 @@ } else { // For an except, the filter can be 1 (catch-all) or a function // label. + assert(Handler->getNumber() >= 0 && "Handler BB was removed"); FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter) : MCConstantExpr::create(1, Ctx); ExceptOrNull = create32bitRef(Handler->getSymbol()); diff --git a/llvm/lib/CodeGen/BranchFolding.cpp b/llvm/lib/CodeGen/BranchFolding.cpp --- a/llvm/lib/CodeGen/BranchFolding.cpp +++ b/llvm/lib/CodeGen/BranchFolding.cpp @@ -124,6 +124,14 @@ if (skipFunction(MF.getFunction())) return false; + // Do not fold branches for MSVC TableSEH function. We have calculated SEH + // states based on old CFG. Folding them may result in invalid labels when + // emitting entries for MSVC C specific handler. + if (MF.getFunction().hasPersonalityFn() && + classifyEHPersonality(MF.getFunction().getPersonalityFn()) == + EHPersonality::MSVC_TableSEH) + return false; + TargetPassConfig *PassConfig = &getAnalysis(); // TailMerge can create jump into if branches that make CFG irreducible for // HW that requires structurized CFG. diff --git a/llvm/test/CodeGen/WinEH/wineh-noret-cleanup.ll b/llvm/test/CodeGen/WinEH/wineh-noret-cleanup.ll --- a/llvm/test/CodeGen/WinEH/wineh-noret-cleanup.ll +++ b/llvm/test/CodeGen/WinEH/wineh-noret-cleanup.ll @@ -64,7 +64,7 @@ ; SEH-NEXT: .long .Ltmp0@IMGREL ; SEH-NEXT: .long .Ltmp1@IMGREL+1 ; SEH-NEXT: .long dummy_filter@IMGREL -; SEH-NEXT: .long .LBB0_3@IMGREL +; SEH-NEXT: .long .LBB0_1@IMGREL ; SEH-NEXT: .long .Ltmp0@IMGREL ; SEH-NEXT: .long .Ltmp1@IMGREL+1 ; SEH-NEXT: .long dummy_filter@IMGREL diff --git a/llvm/test/CodeGen/X86/seh-catchpad.ll b/llvm/test/CodeGen/X86/seh-catchpad.ll --- a/llvm/test/CodeGen/X86/seh-catchpad.ll +++ b/llvm/test/CodeGen/X86/seh-catchpad.ll @@ -135,11 +135,11 @@ ; CHECK-NEXT: .long .Ltmp2@IMGREL ; CHECK-NEXT: .long .Ltmp3@IMGREL+1 ; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL -; CHECK-NEXT: .long .LBB1_3@IMGREL +; CHECK-NEXT: .long .LBB1_8@IMGREL ; CHECK-NEXT: .long .Ltmp6@IMGREL ; CHECK-NEXT: .long .Ltmp7@IMGREL+1 ; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL -; CHECK-NEXT: .long .LBB1_3@IMGREL +; CHECK-NEXT: .long .LBB1_8@IMGREL ; CHECK-NEXT: .Llsda_end0: ; CHECK: .text diff --git a/llvm/test/CodeGen/X86/windows-seh-EHa-CExcept.ll b/llvm/test/CodeGen/X86/windows-seh-EHa-CExcept.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/windows-seh-EHa-CExcept.ll @@ -0,0 +1,63 @@ +; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s + +; CHECK-LABEL: .Llsda_begin0: +; CHECK-NEXT: .long .Ltmp0@IMGREL # LabelStart +; CHECK-NEXT: .long .Ltmp1@IMGREL+1 # LabelEnd +; CHECK-NEXT: .long 1 # CatchAll +; CHECK-NEXT: .long .LBB0_4@IMGREL # ExceptionHandler +; CHECK-NEXT: .long .Ltmp0@IMGREL # LabelStart +; CHECK-NEXT: .long .Ltmp1@IMGREL+1 # LabelEnd +; CHECK-NEXT: .long 1 # CatchAll +; CHECK-NEXT: .long .LBB0_6@IMGREL # ExceptionHandler +; CHECK-NEXT: .long .Ltmp0@IMGREL # LabelStart +; CHECK-NEXT: .long .Ltmp1@IMGREL+1 # LabelEnd +; CHECK-NEXT: .long "?dtor$7@?0?main@4HA"@IMGREL # FinallyFunclet +; CHECK-NEXT: .long 0 # Null + +define dso_local void @main() personality ptr @__C_specific_handler { +entry: + invoke void @llvm.seh.scope.begin() + to label %invoke.cont unwind label %ehcleanup + +invoke.cont: ; preds = %entry + invoke void @llvm.seh.try.begin() + to label %invoke.cont1 unwind label %ehcleanup + +invoke.cont1: ; preds = %invoke.cont + invoke void @llvm.seh.try.begin() + to label %invoke.cont2 unwind label %catch.dispatch10 + +invoke.cont2: ; preds = %invoke.cont1 + invoke void @llvm.seh.try.begin() + to label %invoke.cont4 unwind label %catch.dispatch + +catch.dispatch: ; preds = %invoke.cont2 + %0 = catchswitch within none [label %__except] unwind label %catch.dispatch10 + +__except: ; preds = %catch.dispatch + %1 = catchpad within %0 [ptr null] + unreachable + +invoke.cont4: ; preds = %invoke.cont2 + store volatile i32 1, ptr poison, align 4 + unreachable + +catch.dispatch10: ; preds = %catch.dispatch, %invoke.cont1 + %2 = catchswitch within none [label %__except11] unwind label %ehcleanup + +__except11: ; preds = %catch.dispatch10 + %3 = catchpad within %2 [ptr null] + unreachable + +ehcleanup: ; preds = %catch.dispatch10, %invoke.cont, %entry + %4 = cleanuppad within none [] + cleanupret from %4 unwind to caller +} + +declare dso_local void @llvm.seh.scope.begin() +declare dso_local i32 @__C_specific_handler(...) +declare dso_local void @llvm.seh.try.begin() + +!llvm.module.flags = !{!0} + +!0 = !{i32 2, !"eh-asynch", i32 1}