diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 95 |
1 files changed, 82 insertions, 13 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 35b944ea309..43a4f0111ef 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -196,6 +196,9 @@ public: virtual CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume, BasicBlock *NewBB) = 0; + virtual CloningAction handleCompare(ValueToValueMapTy &VMap, + const CmpInst *Compare, + BasicBlock *NewBB) = 0; virtual CloningAction handleLandingPad(ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) = 0; @@ -231,6 +234,8 @@ public: BasicBlock *NewBB) override; CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume, BasicBlock *NewBB) override; + CloningAction handleCompare(ValueToValueMapTy &VMap, + const CmpInst *Compare, BasicBlock *NewBB) override; CloningAction handleLandingPad(ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) override; @@ -267,6 +272,8 @@ public: BasicBlock *NewBB) override; CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume, BasicBlock *NewBB) override; + CloningAction handleCompare(ValueToValueMapTy &VMap, + const CmpInst *Compare, BasicBlock *NewBB) override; CloningAction handleLandingPad(ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) override; @@ -1053,6 +1060,9 @@ CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction( if (auto *Resume = dyn_cast<ResumeInst>(Inst)) return handleResume(VMap, Resume, NewBB); + if (auto *Cmp = dyn_cast<CmpInst>(Inst)) + return handleCompare(VMap, Cmp, NewBB); + if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) return handleBeginCatch(VMap, Inst, NewBB); if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) @@ -1173,6 +1183,30 @@ WinEHCatchDirector::handleResume(ValueToValueMapTy &VMap, return CloningDirector::StopCloningBB; } +CloningDirector::CloningAction +WinEHCatchDirector::handleCompare(ValueToValueMapTy &VMap, + const CmpInst *Compare, BasicBlock *NewBB) { + const IntrinsicInst *IntrinCall = nullptr; + if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>())) { + IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(0)); + } else if (match(Compare->getOperand(1), m_Intrinsic<Intrinsic::eh_typeid_for>())) { + IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(1)); + } + if (IntrinCall) { + Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts(); + // This causes a replacement that will collapse the landing pad CFG based + // on the filter function we intend to match. + if (Selector == CurrentSelector->stripPointerCasts()) { + VMap[Compare] = ConstantInt::get(SelectorIDType, 1); + } + else { + VMap[Compare] = ConstantInt::get(SelectorIDType, 0); + } + return CloningDirector::SkipInstruction; + } + return CloningDirector::CloneInstruction; +} + CloningDirector::CloningAction WinEHCleanupDirector::handleLandingPad( ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) { // The MS runtime will terminate the process if an exception occurs in a @@ -1189,11 +1223,11 @@ CloningDirector::CloningAction WinEHCleanupDirector::handleLandingPad( CloningDirector::CloningAction WinEHCleanupDirector::handleBeginCatch( ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { - // Catch blocks within cleanup handlers will always be unreachable. - // We'll insert an unreachable instruction now, but it will be pruned - // before the cloning process is complete. - BasicBlock::InstListType &InstList = NewBB->getInstList(); - InstList.push_back(new UnreachableInst(NewBB->getContext())); + // Cleanup code may flow into catch blocks or the catch block may be part + // of a branch that will be optimized away. We'll insert a return + // instruction now, but it may be pruned before the cloning process is + // complete. + ReturnInst::Create(NewBB->getContext(), nullptr, NewBB); return CloningDirector::StopCloningBB; } @@ -1259,6 +1293,19 @@ CloningDirector::CloningAction WinEHCleanupDirector::handleResume( return CloningDirector::StopCloningBB; } +CloningDirector::CloningAction +WinEHCleanupDirector::handleCompare(ValueToValueMapTy &VMap, + const CmpInst *Compare, BasicBlock *NewBB) { + const IntrinsicInst *IntrinCall = nullptr; + if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>()) || + match(Compare->getOperand(1), m_Intrinsic<Intrinsic::eh_typeid_for>())) { + VMap[Compare] = ConstantInt::get(SelectorIDType, 1); + return CloningDirector::SkipInstruction; + } + return CloningDirector::CloneInstruction; + +} + WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer( Function *OutlinedFn, FrameVarInfoMap &FrameVarInfo) : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) { @@ -1355,10 +1402,21 @@ void WinEHPrepare::mapLandingPadBlocks(LandingPadInst *LPad, // See if the clause we're looking for is a catch-all. // If so, the catch begins immediately. - if (isa<ConstantPointerNull>(LPad->getClause(HandlersFound))) { + Constant *ExpectedSelector = LPad->getClause(HandlersFound)->stripPointerCasts(); + if (isa<ConstantPointerNull>(ExpectedSelector)) { // The catch all must occur last. assert(HandlersFound == NumClauses - 1); + // There can be additional selector dispatches in the call chain that we + // need to ignore. + BasicBlock *CatchBlock = nullptr; + Constant *Selector; + while (BB && isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) { + DEBUG(dbgs() << " Found extra catch dispatch in block " + << CatchBlock->getName() << "\n"); + BB = NextBB; + } + // For C++ EH, check if there is any interesting cleanup code before we // begin the catch. This is important because cleanups cannot rethrow // exceptions but code called from catches can. For SEH, it isn't @@ -1368,8 +1426,10 @@ void WinEHPrepare::mapLandingPadBlocks(LandingPadInst *LPad, findCleanupHandlers(Actions, BB, BB); // Add the catch handler to the action list. - CatchHandler *Action = - new CatchHandler(BB, LPad->getClause(HandlersFound), nullptr); + // Since this is a catch-all handler, the selector won't actually appear + // in the code anywhere. ExpectedSelector here is the constant null ptr + // that we got from the landing pad instruction. + CatchHandler *Action = new CatchHandler(BB, ExpectedSelector, nullptr); CatchHandlerMap[BB] = Action; Actions.insertCatchHandler(Action); DEBUG(dbgs() << " Catch all handler at block " << BB->getName() << "\n"); @@ -1385,12 +1445,21 @@ void WinEHPrepare::mapLandingPadBlocks(LandingPadInst *LPad, findCleanupHandlers(Actions, BB, CatchAction->getStartBlock()); assert(CatchAction); - ++HandlersFound; - // Add the catch handler to the action list. - Actions.insertCatchHandler(CatchAction); - DEBUG(dbgs() << " Found catch dispatch in block " - << CatchAction->getStartBlock()->getName() << "\n"); + // When the source program contains multiple nested try blocks the catch + // handlers can get strung together in such a way that we can encounter + // a dispatch for a selector that we've already had a handler for. + if (CatchAction->getSelector()->stripPointerCasts() == ExpectedSelector) { + ++HandlersFound; + + // Add the catch handler to the action list. + DEBUG(dbgs() << " Found catch dispatch in block " + << CatchAction->getStartBlock()->getName() << "\n"); + Actions.insertCatchHandler(CatchAction); + } else { + DEBUG(dbgs() << " Found extra catch dispatch in block " + << CatchAction->getStartBlock()->getName() << "\n"); + } // Move on to the block after the catch handler. BB = NextBB; |