[WinEH] Fixes for a few cppeh failures.

Differential Review: http://reviews.llvm.org/D9065



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235239 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Kaylor
2015-04-17 23:05:43 +00:00
parent ee5f9c6278
commit 166679ef06
3 changed files with 619 additions and 13 deletions

View File

@@ -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;