diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-04-17 01:01:27 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2015-04-17 01:01:27 +0000 |
commit | d4523e3c5189dfefe4d59a1d226eefa624edeae1 (patch) | |
tree | d8cf75f6bde24a7014ec5264aa8769bbfffc0999 /llvm/lib/CodeGen/SelectionDAG | |
parent | de50d36ab39b9d591bae6562f76a6e0c3169e84b (diff) | |
download | bcm5719-llvm-d4523e3c5189dfefe4d59a1d226eefa624edeae1.tar.gz bcm5719-llvm-d4523e3c5189dfefe4d59a1d226eefa624edeae1.zip |
[SEH] Reimplement x64 SEH using WinEHPrepare
This now emits simple, unoptimized xdata tables for __C_specific_handler
based on the handlers listed in @llvm.eh.actions calls produced by
WinEHPrepare.
This adds support for running __finally blocks when exceptions are
thrown, and removes the old landingpad fan-in codepath.
I ran some manual execution tests on small basic test cases with and
without optimization, as well as on Chrome base_unittests, which uses a
small amount of SEH. I'm sure there are bugs, and we may need to
revert.
llvm-svn: 235154
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 56 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 87 |
2 files changed, 78 insertions, 65 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; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 1e116dddafa..0478c7382f2 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,70 +937,28 @@ 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 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. - for (const BasicBlock *LLVMSucc : successors(LLVMBB)) { - MachineBasicBlock *ClauseBB = FuncInfo->MBBMap[LLVMSucc]; - // Add the edge from the invoke to the clause. - for (MachineBasicBlock *InvokeBB : InvokeBBs) - InvokeBB->addSuccessor(ClauseBB); - } - } 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. - - // Make virtual registers and a series of labels that fill in values for - // the clauses. - auto &RI = MF->getRegInfo(); - FuncInfo->ExceptionSelectorVirtReg = RI.createVirtualRegister(PtrRC); - - // Emit separate machine basic blocks with separate labels for each clause - // before the main landing pad block. - MachineInstrBuilder SelectorPHI = BuildMI( - *MBB, MBB->begin(), SDB->getCurDebugLoc(), - TII->get(TargetOpcode::PHI), FuncInfo->ExceptionSelectorVirtReg); - for (unsigned I = 0, E = LPadInst->getNumClauses(); I != E; ++I) { - // Skip filter clauses, we can't implement them. - if (LPadInst->isFilter(I)) - continue; - - MachineBasicBlock *ClauseBB = MF->CreateMachineBasicBlock(LLVMBB); - MF->insert(MBB, ClauseBB); - - // 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(); - - GlobalValue *ClauseGV = ExtractTypeInfo(LPadInst->getClause(I)); - - // Start the BB with a label. - MCSymbol *ClauseLabel = MF->getMMI().addClauseForLandingPad(MBB); - BuildMI(*ClauseBB, ClauseBB->begin(), SDB->getCurDebugLoc(), II) - .addSym(ClauseLabel); - - // Construct a simple BB that defines a register with the typeid - // constant. - FuncInfo->MBB = ClauseBB; - FuncInfo->InsertPt = ClauseBB->end(); - unsigned VReg = SDB->visitLandingPadClauseBB(ClauseGV, MBB); - CurDAG->setRoot(SDB->getRoot()); - SDB->clear(); - CodeGenAndEmitDAG(); + if (!ActionsCall || ActionsCall->getIntrinsicID() != Intrinsic::eh_actions) { + assert(isa<UnreachableInst>(LLVMBB->getFirstInsertionPt()) && + "found landingpad without unreachable or llvm.eh.actions"); + return false; + } - // Add the typeid virtual register to the phi in the main landing pad. - SelectorPHI.addReg(VReg).addMBB(ClauseBB); - } + // 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. + for (const BasicBlock *LLVMSucc : successors(LLVMBB)) { + MachineBasicBlock *ClauseBB = FuncInfo->MBBMap[LLVMSucc]; + // 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(); } // Remove the edge from the invoke to the lpad. @@ -1017,7 +975,9 @@ void SelectionDAGISel::PrepareEHLandingPad() { WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction()); MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]); } - return; + + // Don't select instructions for landing pads using llvm.eh.actions. + return false; } // Mark exception register as live in. @@ -1027,6 +987,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 +1159,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) { |