if (!isFuncletEHPersonality(Personality))
return false;
+ // Remove unreachable blocks. It is not valuable to assign them a color and
+ // their existence can trick us into thinking values are alive when they are
+ // not.
+ removeUnreachableBlocks(Fn);
+
SmallVector<LandingPadInst *, 4> LPads;
SmallVector<ResumeInst *, 4> Resumes;
SmallVector<BasicBlock *, 4> EntryBlocks;
}
IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
Function *EHCodeFn = Intrinsic::getDeclaration(
- StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode);
+ StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode_old);
Value *Code = Builder.CreateCall(EHCodeFn, {}, "sehcode");
Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType());
Builder.CreateStore(Code, SEHExceptionCodeSlot);
DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh
<< '\n');
} else if (isa<CleanupPadInst>(FirstNonPHI)) {
+ // A cleanup can have multiple exits; don't re-process after the first.
+ if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
+ return;
int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
for (const BasicBlock *PredBlock : predecessors(&BB))
if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState);
+ } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
+ // Propagate ParentState to the cleanuppad in case it doesn't have
+ // any cleanuprets.
+ BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
+ calculateExplicitCXXStateNumbers(FuncInfo, *CleanupBlock, ParentState);
+ // Anything unwinding through CleanupEndPadInst is in ParentState.
+ for (const BasicBlock *PredBlock : predecessors(&BB))
+ if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+ calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, ParentState);
} else if (isa<TerminatePadInst>(FirstNonPHI)) {
report_fatal_error("Not yet implemented!");
} else {
if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
} else if (isa<CleanupPadInst>(FirstNonPHI)) {
+ // A cleanup can have multiple exits; don't re-process after the first.
+ if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
+ return;
int CleanupState = addSEHFinally(FuncInfo, ParentState, &BB);
FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
for (const BasicBlock *PredBlock : predecessors(&BB))
if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState);
- } else if (isa<CleanupEndPadInst>(FirstNonPHI)) {
+ } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
+ // Propagate ParentState to the cleanuppad in case it doesn't have
+ // any cleanuprets.
+ BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
+ calculateExplicitSEHStateNumbers(FuncInfo, *CleanupBlock, ParentState);
// Anything unwinding through CleanupEndPadInst is in ParentState.
FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
if (BB.isLandingPad())
report_fatal_error("MSVC C++ EH cannot use landingpads");
const Instruction *FirstNonPHI = BB.getFirstNonPHI();
- // Skip cleanupendpads; they are exits, not entries.
- if (isa<CleanupEndPadInst>(FirstNonPHI))
- continue;
if (!doesEHPadUnwindToCaller(FirstNonPHI))
continue;
calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
// Preds of the endpad should get the parent state.
PredState = ParentState;
} else if (const CatchPadInst *Catch = dyn_cast<CatchPadInst>(Pad)) {
- const BasicBlock *Handler = Catch->getNormalDest();
+ const BasicBlock *PadBlock = Catch->getParent();
uint32_t TypeToken = static_cast<uint32_t>(
cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
int NewState = addClrEHHandler(FuncInfo, ParentState,
- ClrHandlerType::Catch, TypeToken, Handler);
+ ClrHandlerType::Catch, TypeToken, PadBlock);
FuncInfo.EHPadStateMap[Catch] = NewState;
// Preds of the catch get its state
PredState = NewState;
// Mark this as a funclet head as a member of itself.
FuncletBlocks[Visiting].insert(Visiting);
// Queue exits with the parent color.
- for (User *Exit : VisitingHead->users()) {
- for (BasicBlock *Succ :
- successors(cast<Instruction>(Exit)->getParent())) {
- if (BlockColors[Succ].insert(Color).second) {
- Worklist.push_back({Succ, Color});
- }
+ for (User *U : VisitingHead->users()) {
+ if (auto *Exit = dyn_cast<TerminatorInst>(U)) {
+ for (BasicBlock *Succ : successors(Exit->getParent()))
+ if (BlockColors[Succ].insert(Color).second)
+ Worklist.push_back({Succ, Color});
}
}
// Handle CatchPad specially since its successors need different colors.
// The users of a catchpad are always catchrets.
for (User *Exit : CatchPad->users()) {
- auto *CatchReturn = cast<CatchReturnInst>(Exit);
+ auto *CatchReturn = dyn_cast<CatchReturnInst>(Exit);
+ if (!CatchReturn)
+ continue;
BasicBlock *CatchRetSuccessor = CatchReturn->getSuccessor();
std::set<BasicBlock *> &SuccessorColors = BlockColors[CatchRetSuccessor];
assert(SuccessorColors.size() == 1 && "Expected BB to be monochrome!");
Orig2Clone[BB] = CBB;
}
+ // If nothing was cloned, we're done cloning in this funclet.
+ if (Orig2Clone.empty())
+ continue;
+
// Update our color mappings to reflect that one block has lost a color and
// another has gained a color.
for (auto &BBMapping : Orig2Clone) {
BlockColors[OldBlock].erase(FuncletPadBB);
}
- // Loop over all of the instructions in the function, fixing up operand
+ // Loop over all of the instructions in this funclet, fixing up operand
// references as we go. This uses VMap to do all the hard work.
for (BasicBlock *BB : BlocksInFunclet)
// Loop over all instructions, fixing each one as we find it...
for (Instruction &I : *BB)
- RemapInstruction(&I, VMap, RF_IgnoreMissingEntries);
+ RemapInstruction(&I, VMap,
+ RF_IgnoreMissingEntries | RF_NoModuleLevelChanges);
// Check to see if SuccBB has PHI nodes. If so, we need to add entries to
// the PHI nodes for NewBB now.
bool WinEHPrepare::prepareExplicitEH(
Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
- // Remove unreachable blocks. It is not valuable to assign them a color and
- // their existence can trick us into thinking values are alive when they are
- // not.
- removeUnreachableBlocks(F);
-
replaceTerminatePadWithCleanup(F);
// Determine which blocks are reachable from which funclet entries.