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;
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;
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;
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>()))
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
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;
}
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()) {
// 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
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");
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;