diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp | 58 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineModuleInfo.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 56 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 87 | ||||
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 15 |
5 files changed, 119 insertions, 118 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp index 9420fb24427..f89d36455f4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -206,14 +206,15 @@ void Win64Exception::emitCSpecificHandlerTable() { for (const CallSiteEntry &CSE : CallSites) { if (!CSE.LPad) continue; // Ignore gaps. - NumEntries += CSE.LPad->SEHHandlers.size(); + for (int Selector : CSE.LPad->TypeIds) { + // Ignore C++ filter clauses in SEH. + // FIXME: Implement cleanup clauses. + if (isCatchEHSelector(Selector)) + ++NumEntries; + } } 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) { @@ -239,27 +240,36 @@ void Win64Exception::emitCSpecificHandlerTable() { End = createImageRel32(EHFuncEndSym); } - // Emit an entry for each action. - for (SEHHandler Handler : LPad->SEHHandlers) { + // 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. + const std::vector<const GlobalValue *> &SelectorToFilter = MMI->getTypeInfos(); + + // Do a parallel iteration across typeids and clause labels, skipping filter + // clauses. + size_t NextClauseLabel = 0; + for (size_t I = 0, E = LPad->TypeIds.size(); I < E; ++I) { + // AddLandingPadInfo stores the clauses in reverse, but there is a FIXME + // to change that. + int Selector = LPad->TypeIds[E - I - 1]; + + // Ignore C++ filter clauses in SEH. + // FIXME: Implement cleanup clauses. + if (!isCatchEHSelector(Selector)) + continue; + 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 (isCatchEHSelector(Selector)) { + assert(unsigned(Selector - 1) < SelectorToFilter.size()); + const GlobalValue *TI = SelectorToFilter[Selector - 1]; + if (TI) // Emit the filter function pointer. + Asm->OutStreamer.EmitValue(createImageRel32(Asm->getSymbol(TI)), 4); + else // Otherwise, this is a "catch i8* null", or catch all. + Asm->OutStreamer.EmitIntValue(1, 4); + } + MCSymbol *ClauseLabel = LPad->ClauseLabels[NextClauseLabel++]; + Asm->OutStreamer.EmitValue(createImageRel32(ClauseLabel), 4); } } } diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp index 2352692aca5..e8bd1f8e6d9 100644 --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -461,23 +461,12 @@ void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) { LP.TypeIds.push_back(0); } -void MachineModuleInfo::addSEHCatchHandler(MachineBasicBlock *LandingPad, - const Function *Filter, - const BlockAddress *RecoverBA) { +MCSymbol * +MachineModuleInfo::addClauseForLandingPad(MachineBasicBlock *LandingPad) { + MCSymbol *ClauseLabel = Context.CreateTempSymbol(); 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); + LP.ClauseLabels.push_back(ClauseLabel); + return ClauseLabel; } /// TidyLandingPads - Remap landing pad labels and remove any deleted landing diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index bb40326ba2d..4b8ae32e9a5 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -270,21 +270,12 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, } // Mark landing pad blocks. - const LandingPadInst *LP = nullptr; - for (BB = Fn->begin(); BB != EB; ++BB) { + 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 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) { + // Calculate EH numbers for WinEH. + if (fn.hasFnAttribute("wineh-parent")) { const Function *WinEHParentFn = MMI.getWinEHParent(&fn); WinEHFuncInfo &FI = MMI.getWinEHFuncInfo(WinEHParentFn); if (FI.LandingPadStateMap.empty()) { @@ -296,47 +287,6 @@ 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 0478c7382f2..1e116dddafa 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. -bool SelectionDAGISel::PrepareEHLandingPad() { +void SelectionDAGISel::PrepareEHLandingPad() { MachineBasicBlock *MBB = FuncInfo->MBB; const TargetRegisterClass *PtrRC = TLI->getRegClassFor(TLI->getPointerTy()); @@ -937,28 +937,70 @@ bool SelectionDAGISel::PrepareEHLandingPad() { if (isMSVCEHPersonality(Personality)) { SmallVector<MachineBasicBlock *, 4> ClauseBBs; - const IntrinsicInst *ActionsCall = + const IntrinsicInst *Actions = 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 (!ActionsCall || ActionsCall->getIntrinsicID() != Intrinsic::eh_actions) { - assert(isa<UnreachableInst>(LLVMBB->getFirstInsertionPt()) && - "found landingpad without unreachable or llvm.eh.actions"); - return false; - } + 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); - // 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(); + // 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(); + + // Add the typeid virtual register to the phi in the main landing pad. + SelectorPHI.addReg(VReg).addMBB(ClauseBB); + } } // Remove the edge from the invoke to the lpad. @@ -975,9 +1017,7 @@ bool SelectionDAGISel::PrepareEHLandingPad() { WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction()); MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]); } - - // Don't select instructions for landing pads using llvm.eh.actions. - return false; + return; } // Mark exception register as live in. @@ -987,8 +1027,6 @@ bool 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 @@ -1159,8 +1197,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FuncInfo->ExceptionPointerVirtReg = 0; FuncInfo->ExceptionSelectorVirtReg = 0; if (LLVMBB->isLandingPad()) - if (!PrepareEHLandingPad()) - continue; + PrepareEHLandingPad(); // Before doing SelectionDAG ISel, see if FastISel has been requested. if (FastIS) { diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index e573f3e7f41..35b944ea309 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -306,6 +306,11 @@ FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { return new WinEHPrepare(TM); } +// FIXME: Remove this once the backend can handle the prepared IR. +static cl::opt<bool> + SEHPrepare("sehprepare", cl::Hidden, + cl::desc("Prepare functions with SEH personalities")); + bool WinEHPrepare::runOnFunction(Function &Fn) { SmallVector<LandingPadInst *, 4> LPads; SmallVector<ResumeInst *, 4> Resumes; @@ -329,6 +334,16 @@ bool WinEHPrepare::runOnFunction(Function &Fn) { DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + if (isAsynchronousEHPersonality(Personality) && !SEHPrepare) { + // Replace all resume instructions with unreachable. + // FIXME: Remove this once the backend can handle the prepared IR. + for (ResumeInst *Resume : Resumes) { + IRBuilder<>(Resume).CreateUnreachable(); + Resume->eraseFromParent(); + } + return true; + } + // If there were any landing pads, prepareExceptionHandlers will make changes. prepareExceptionHandlers(Fn, LPads); return true; |