diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 4b8ae32e9a5..bb40326ba2d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -270,12 +270,21 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, } // Mark landing pad blocks. - for (BB = Fn->begin(); BB != EB; ++BB) + const LandingPadInst *LP = nullptr; + for (BB = Fn->begin(); BB != EB; ++BB) { if (const auto *Invoke = dyn_cast<InvokeInst>(BB->getTerminator())) MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); + if (BB->isLandingPad()) + LP = BB->getLandingPadInst(); + } - // Calculate EH numbers for WinEH. - if (fn.hasFnAttribute("wineh-parent")) { + // Calculate EH numbers for MSVC C++ EH and save SEH handlers if necessary. + EHPersonality Personality = EHPersonality::Unknown; + if (LP) + Personality = classifyEHPersonality(LP->getPersonalityFn()); + if (Personality == EHPersonality::MSVC_Win64SEH) { + addSEHHandlersForLPads(); + } else if (Personality == EHPersonality::MSVC_CXX) { const Function *WinEHParentFn = MMI.getWinEHParent(&fn); WinEHFuncInfo &FI = MMI.getWinEHFuncInfo(WinEHParentFn); if (FI.LandingPadStateMap.empty()) { @@ -287,6 +296,47 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, } } +void FunctionLoweringInfo::addSEHHandlersForLPads() { + MachineModuleInfo &MMI = MF->getMMI(); + + // Iterate over all landing pads with llvm.eh.actions calls. + for (const BasicBlock &BB : *Fn) { + const LandingPadInst *LP = BB.getLandingPadInst(); + if (!LP) + continue; + const IntrinsicInst *ActionsCall = + dyn_cast<IntrinsicInst>(LP->getNextNode()); + if (!ActionsCall || + ActionsCall->getIntrinsicID() != Intrinsic::eh_actions) + continue; + + // Parse the llvm.eh.actions call we found. + MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()]; + SmallVector<ActionHandler *, 4> Actions; + parseEHActions(ActionsCall, Actions); + + // Iterate EH actions from most to least precedence, which means + // iterating in reverse. + for (auto I = Actions.rbegin(), E = Actions.rend(); I != E; ++I) { + ActionHandler *Action = *I; + if (auto *CH = dyn_cast<CatchHandler>(Action)) { + const auto *Filter = + dyn_cast<Function>(CH->getSelector()->stripPointerCasts()); + assert((Filter || CH->getSelector()->isNullValue()) && + "expected function or catch-all"); + const auto *RecoverBA = + cast<BlockAddress>(CH->getHandlerBlockOrFunc()); + MMI.addSEHCatchHandler(LPadMBB, Filter, RecoverBA); + } else { + assert(isa<CleanupHandler>(Action)); + const auto *Fini = cast<Function>(Action->getHandlerBlockOrFunc()); + MMI.addSEHCleanupHandler(LPadMBB, Fini); + } + } + DeleteContainerPointers(Actions); + } +} + void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) { WinEHUnwindMapEntry UME; UME.ToState = ToState; |