diff --git a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h --- a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h @@ -116,7 +116,7 @@ /// describes the state numbers and tables used by __CxxFrameHandler3. This /// analysis assumes that WinEHPrepare has already been run. void calculateWinCXXEHStateNumbers(const Function *ParentFn, - WinEHFuncInfo &FuncInfo); + WinEHFuncInfo &FuncInfo, bool Is64Bit); void calculateSEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo); diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -103,8 +103,9 @@ if (isFuncletEHPersonality(Personality)) { // Calculate state numbers if we haven't already. WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo(); + Triple::ArchType Arch = MF->getSubtarget().getTargetTriple().getArch(); if (Personality == EHPersonality::MSVC_CXX) - calculateWinCXXEHStateNumbers(&fn, EHInfo); + calculateWinCXXEHStateNumbers(&fn, EHInfo, Arch == Triple::x86_64); else if (isAsynchronousEHPersonality(Personality)) calculateSEHStateNumbers(&fn, EHInfo); else if (Personality == EHPersonality::CoreCLR) 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 @@ -137,9 +137,9 @@ return FuncInfo.getLastStateNumber(); } -static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow, - int TryHigh, int CatchHigh, - ArrayRef Handlers) { +static WinEHTryBlockMapEntry* +addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow, int TryHigh, + int CatchHigh, ArrayRef Handlers) { WinEHTryBlockMapEntry TBME; TBME.TryLow = TryLow; TBME.TryHigh = TryHigh; @@ -162,6 +162,7 @@ TBME.HandlerArray.push_back(HT); } FuncInfo.TryBlockMap.push_back(TBME); + return &FuncInfo.TryBlockMap.back(); } static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad) { @@ -239,7 +240,7 @@ // FuncInfo.EHPadStateMap[] and FuncInfo.CxxUnwindMap[] static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo, const Instruction *FirstNonPHI, - int ParentState) { + int ParentState, bool Is64Bit) { const BasicBlock *BB = FirstNonPHI->getParent(); assert(BB->isEHPad() && "not a funclet!"); @@ -258,11 +259,14 @@ if ((PredBlock = getEHPadFromPredecessor(PredBlock, CatchSwitch->getParentPad()))) calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(), - TryLow); + TryLow, Is64Bit); int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr); // catchpads are separate funclets in C++ EH due to the way rethrow works. int TryHigh = CatchLow - 1; + WinEHTryBlockMapEntry *TBME = nullptr; + if (Is64Bit) + TBME = addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, 0, Handlers); for (const auto *CatchPad : Handlers) { FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow; for (const User *U : CatchPad->users()) { @@ -270,7 +274,7 @@ if (auto *InnerCatchSwitch = dyn_cast(UserI)) { BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest(); if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) - calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); + calculateCXXStateNumbers(FuncInfo, UserI, CatchLow, Is64Bit); } if (auto *InnerCleanupPad = dyn_cast(UserI)) { BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad); @@ -278,17 +282,21 @@ // enclosing catch pad doesn't it must be post-dominated by an // unreachable instruction. if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) - calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); + calculateCXXStateNumbers(FuncInfo, UserI, CatchLow, Is64Bit); } } } - int CatchHigh = FuncInfo.getLastStateNumber(); - addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers); - LLVM_DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n'); - LLVM_DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh + + if (!Is64Bit) + TBME = addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, 0, Handlers); + + TBME->CatchHigh = FuncInfo.getLastStateNumber(); + LLVM_DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TBME->TryLow << '\n'); - LLVM_DEBUG(dbgs() << "CatchHigh[" << BB->getName() << "]: " << CatchHigh + LLVM_DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TBME->TryHigh << '\n'); + LLVM_DEBUG(dbgs() << "CatchHigh[" << BB->getName() << "]: " + << TBME->CatchHigh << '\n'); } else { auto *CleanupPad = cast(FirstNonPHI); @@ -305,7 +313,7 @@ if ((PredBlock = getEHPadFromPredecessor(PredBlock, CleanupPad->getParentPad()))) { calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(), - CleanupState); + CleanupState, Is64Bit); } } for (const User *U : CleanupPad->users()) { @@ -451,7 +459,8 @@ } void llvm::calculateWinCXXEHStateNumbers(const Function *Fn, - WinEHFuncInfo &FuncInfo) { + WinEHFuncInfo &FuncInfo, + bool Is64Bit) { // Return if it's already been done. if (!FuncInfo.EHPadStateMap.empty()) return; @@ -462,7 +471,7 @@ const Instruction *FirstNonPHI = BB.getFirstNonPHI(); if (!isTopLevelPadForMSVC(FirstNonPHI)) continue; - calculateCXXStateNumbers(FuncInfo, FirstNonPHI, -1); + calculateCXXStateNumbers(FuncInfo, FirstNonPHI, -1, Is64Bit); } calculateStateNumbersForInvokes(Fn, FuncInfo); diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -644,7 +644,7 @@ if (isAsynchronousEHPersonality(Personality)) calculateSEHStateNumbers(&F, FuncInfo); else - calculateWinCXXEHStateNumbers(&F, FuncInfo); + calculateWinCXXEHStateNumbers(&F, FuncInfo, false); // Iterate all the instructions and emit state number stores. DenseMap BlockColors = colorEHFunclets(F); 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 @@ -62,17 +62,29 @@ ; EHFlags ; 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) +; X86-LABEL: $tryMap$try_in_catch: +; X86-NEXT: .long 2 +; X86-NEXT: .long 2 +; X86-NEXT: .long 3 +; X86-NEXT: .long 1 +; X86-NEXT: .long ($handlerMap$0$try_in_catch) +; X86-NEXT: .long 0 +; X86-NEXT: .long 0 +; X86-NEXT: .long 3 +; X86-NEXT: .long 1 +; X86-NEXT: .long ($handlerMap$1$try_in_catch) + +; X64-LABEL: $tryMap$try_in_catch: +; X64-NEXT: .long 0 +; X64-NEXT: .long 0 +; X64-NEXT: .long 3 +; X64-NEXT: .long 1 +; X64-NEXT: .long ($handlerMap$0$try_in_catch) +; X64-NEXT: .long 2 +; X64-NEXT: .long 2 +; X64-NEXT: .long 3 +; X64-NEXT: .long 1 +; X64-NEXT: .long ($handlerMap$1$try_in_catch) ; CHECK: $handlerMap$0$try_in_catch: ; CHECK-NEXT: .long 64