diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -263,6 +263,13 @@ // catchpads are separate funclets in C++ EH due to the way rethrow works. int TryHigh = CatchLow - 1; + + // MSVC FrameHandler3/4 expect Catch Handlers in $tryMap$ are + // stored in pre-order (outer first, inner next), not post-order + // Add to map here. Fix the CatchHIgh after children are processed + addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchLow, Handlers); + unsigned TBMEIdx = FuncInfo.TryBlockMap.size() - 1; + for (const auto *CatchPad : Handlers) { FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow; for (const User *U : CatchPad->users()) { @@ -283,7 +290,9 @@ } } int CatchHigh = FuncInfo.getLastStateNumber(); - addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers); + // Now child Catches are processed, update CatchHigh + FuncInfo.TryBlockMap[TBMEIdx].CatchHigh = CatchHigh; + LLVM_DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n'); LLVM_DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh << '\n'); diff --git a/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll b/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll --- a/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll +++ b/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll @@ -63,16 +63,16 @@ ; CHECK-NEXT: .long 1 ; CHECK: $tryMap$try_in_catch: -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long 3 -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long ($handlerMap$0$try_in_catch) ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long 0 ; CHECK-NEXT: .long 3 ; CHECK-NEXT: .long 1 ; CHECK-NEXT: .long ($handlerMap$1$try_in_catch) +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long ($handlerMap$0$try_in_catch) ; CHECK: $handlerMap$0$try_in_catch: ; CHECK-NEXT: .long 64