diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineModuleInfo.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 56 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 20 |
4 files changed, 117 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp index 8c90bed2b5a..2737a5323d6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -212,9 +212,14 @@ void Win64Exception::emitCSpecificHandlerTable() { if (isCatchEHSelector(Selector)) ++NumEntries; } + NumEntries += CSE.LPad->SEHHandlers.size(); } Asm->OutStreamer.EmitIntValue(NumEntries, 4); + // If there are no actions, we don't need to iterate again. + if (NumEntries == 0) + return; + // Emit the four-label records for each call site entry. The table has to be // sorted in layout order, and the call sites should already be sorted. for (const CallSiteEntry &CSE : CallSites) { @@ -240,6 +245,31 @@ void Win64Exception::emitCSpecificHandlerTable() { End = createImageRel32(EHFuncEndSym); } + // Emit an entry for each action. + for (SEHHandler Handler : LPad->SEHHandlers) { + Asm->OutStreamer.EmitValue(Begin, 4); + Asm->OutStreamer.EmitValue(End, 4); + + // Emit the filter or finally function pointer, if present. Otherwise, + // emit '1' to indicate a catch-all. + const Function *F = Handler.FilterOrFinally; + if (F) + Asm->OutStreamer.EmitValue(createImageRel32(Asm->getSymbol(F)), 4); + else + Asm->OutStreamer.EmitIntValue(1, 4); + + // Emit the recovery address, if present. Otherwise, this must be a + // finally. + const BlockAddress *BA = Handler.RecoverBA; + if (BA) + Asm->OutStreamer.EmitValue( + createImageRel32(Asm->GetBlockAddressSymbol(BA)), 4); + else + Asm->OutStreamer.EmitIntValue(0, 4); + } + if (!LPad->SEHHandlers.empty()) + continue; + // These aren't really type info globals, they are actually pointers to // filter functions ordered by selector. The zero selector is used for // cleanups, so slot zero corresponds to selector 1. diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp index e8bd1f8e6d9..e4f2aea287f 100644 --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -469,6 +469,25 @@ MachineModuleInfo::addClauseForLandingPad(MachineBasicBlock *LandingPad) { return ClauseLabel; } +void MachineModuleInfo::addSEHCatchHandler(MachineBasicBlock *LandingPad, + const Function *Filter, + const BlockAddress *RecoverBA) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + SEHHandler Handler; + Handler.FilterOrFinally = Filter; + Handler.RecoverBA = RecoverBA; + LP.SEHHandlers.push_back(Handler); +} + +void MachineModuleInfo::addSEHCleanupHandler(MachineBasicBlock *LandingPad, + const Function *Cleanup) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + SEHHandler Handler; + Handler.FilterOrFinally = Cleanup; + Handler.RecoverBA = nullptr; + LP.SEHHandlers.push_back(Handler); +} + /// TidyLandingPads - Remap landing pad labels and remove any deleted landing /// pads. void MachineModuleInfo::TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap) { 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; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 1e116dddafa..235cda64776 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -911,7 +911,7 @@ void SelectionDAGISel::DoInstructionSelection() { /// PrepareEHLandingPad - Emit an EH_LABEL, set up live-in registers, and /// do other setup for EH landing-pad blocks. -void SelectionDAGISel::PrepareEHLandingPad() { +bool SelectionDAGISel::PrepareEHLandingPad() { MachineBasicBlock *MBB = FuncInfo->MBB; const TargetRegisterClass *PtrRC = TLI->getRegClassFor(TLI->getPointerTy()); @@ -937,12 +937,12 @@ void SelectionDAGISel::PrepareEHLandingPad() { if (isMSVCEHPersonality(Personality)) { SmallVector<MachineBasicBlock *, 4> ClauseBBs; - const IntrinsicInst *Actions = + const IntrinsicInst *ActionsCall = dyn_cast<IntrinsicInst>(LLVMBB->getFirstInsertionPt()); // Get all invoke BBs that unwind to this landingpad. SmallVector<MachineBasicBlock *, 4> InvokeBBs(MBB->pred_begin(), MBB->pred_end()); - if (Actions && Actions->getIntrinsicID() == Intrinsic::eh_actions) { + if (ActionsCall && ActionsCall->getIntrinsicID() == Intrinsic::eh_actions) { // If this is a call to llvm.eh.actions followed by indirectbr, then we've // run WinEHPrepare, and we should remove this block from the machine CFG. // Mark the targets of the indirectbr as landingpads instead. @@ -951,11 +951,15 @@ void SelectionDAGISel::PrepareEHLandingPad() { // Add the edge from the invoke to the clause. for (MachineBasicBlock *InvokeBB : InvokeBBs) InvokeBB->addSuccessor(ClauseBB); + + // Mark the clause as a landing pad or MI passes will delete it. + ClauseBB->setIsLandingPad(); } } else { // Otherwise, we haven't done the preparation, and we need to invent some // clause basic blocks that branch into the landingpad. // FIXME: Remove this code once SEH preparation works. + ActionsCall = nullptr; // Make virtual registers and a series of labels that fill in values for // the clauses. @@ -1017,7 +1021,10 @@ void SelectionDAGISel::PrepareEHLandingPad() { WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction()); MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]); } - return; + + // Select instructions for the landingpad if there was no llvm.eh.actions + // call. + return ActionsCall == nullptr; } // Mark exception register as live in. @@ -1027,6 +1034,8 @@ void SelectionDAGISel::PrepareEHLandingPad() { // Mark exception selector register as live in. if (unsigned Reg = TLI->getExceptionSelectorRegister()) FuncInfo->ExceptionSelectorVirtReg = MBB->addLiveIn(Reg, PtrRC); + + return true; } /// isFoldedOrDeadInstruction - Return true if the specified instruction is @@ -1197,7 +1206,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FuncInfo->ExceptionPointerVirtReg = 0; FuncInfo->ExceptionSelectorVirtReg = 0; if (LLVMBB->isLandingPad()) - PrepareEHLandingPad(); + if (!PrepareEHLandingPad()) + continue; // Before doing SelectionDAG ISel, see if FastISel has been requested. if (FastIS) { |