/// Assign every distinct landingpad a unique state number for SEH. Unlike C++ /// EH, we can use this very simple algorithm while C++ EH cannot because catch /// handlers aren't outlined and the runtime doesn't have to figure out which /// catch handler frame to unwind to. /// FIXME: __finally blocks are outlined, so this approach may break down there. void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) { WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F); // Remember and return the index that we used. We save it in WinEHFuncInfo so // that we can lower llvm.x86.seh.recoverfp later in filter functions without // too much trouble. int RegNodeEscapeIndex = escapeRegNode(F); FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; // Iterate all the instructions and emit state number stores. int CurState = 0; SmallPtrSet<BasicBlock *, 4> ExceptBlocks; for (BasicBlock &BB : F) { for (auto I = BB.begin(), E = BB.end(); I != E; ++I) { if (auto *CI = dyn_cast<CallInst>(I)) { auto *Intrin = dyn_cast<IntrinsicInst>(CI); if (Intrin) { // Calls that "don't throw" are considered to be able to throw asynch // exceptions, but intrinsics cannot. continue; } insertStateNumberStore(RegNode, CI, -1); } else if (auto *II = dyn_cast<InvokeInst>(I)) { // Look up the state number of the landingpad this unwinds to. LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst(); auto InsertionPair = FuncInfo.LandingPadStateMap.insert(std::make_pair(LPI, CurState)); auto Iter = InsertionPair.first; int &State = Iter->second; bool Inserted = InsertionPair.second; if (Inserted) { // Each action consumes a state number. auto *EHActions = cast<IntrinsicInst>(LPI->getNextNode()); SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList; parseEHActions(EHActions, ActionList); assert(!ActionList.empty()); CurState += ActionList.size(); State += ActionList.size() - 1; // Remember all the __except block targets. for (auto &Handler : ActionList) { if (auto *CH = dyn_cast<CatchHandler>(Handler.get())) { auto *BA = cast<BlockAddress>(CH->getHandlerBlockOrFunc()); ExceptBlocks.insert(BA->getBasicBlock()); } } } insertStateNumberStore(RegNode, II, State); } } } // Insert llvm.x86.seh.restoreframe() into each __except block. Function *RestoreFrame = Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe); for (BasicBlock *ExceptBB : ExceptBlocks) { IRBuilder<> Builder(ExceptBB->begin()); Builder.CreateCall(RestoreFrame, {}); } }
/// Assign every distinct landingpad a unique state number for SEH. Unlike C++ /// EH, we can use this very simple algorithm while C++ EH cannot because catch /// handlers aren't outlined and the runtime doesn't have to figure out which /// catch handler frame to unwind to. /// FIXME: __finally blocks are outlined, so this approach may break down there. void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) { // Remember and return the index that we used. We save it in WinEHFuncInfo so // that we can lower llvm.x86.seh.recoverfp later in filter functions without // too much trouble. int RegNodeEscapeIndex = escapeRegNode(F); FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; // If this funciton uses the new EH IR, use the explicit state numbering // algorithm and return early. bool UsesLPads = false; for (BasicBlock &BB : F) { if (BB.isLandingPad()) { UsesLPads = true; break; } } if (!UsesLPads) { calculateSEHStateNumbers(&F, FuncInfo); addStateStoresToFunclet(RegNode, FuncInfo, F, -1); return; } // FIXME: Delete the rest of this code and clean things up when new EH is // done. // Iterate all the instructions and emit state number stores. int CurState = 0; SmallPtrSet<BasicBlock *, 4> ExceptBlocks; for (BasicBlock &BB : F) { for (auto I = BB.begin(), E = BB.end(); I != E; ++I) { if (auto *CI = dyn_cast<CallInst>(I)) { auto *Intrin = dyn_cast<IntrinsicInst>(CI); if (Intrin) { // Calls that "don't throw" are considered to be able to throw asynch // exceptions, but intrinsics cannot. continue; } insertStateNumberStore(RegNode, CI, -1); } else if (auto *II = dyn_cast<InvokeInst>(I)) { // Look up the state number of the landingpad this unwinds to. LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst(); auto InsertionPair = FuncInfo.EHPadStateMap.insert(std::make_pair(LPI, CurState)); auto Iter = InsertionPair.first; int &State = Iter->second; bool Inserted = InsertionPair.second; if (Inserted) { // Each action consumes a state number. auto *EHActions = cast<IntrinsicInst>(LPI->getNextNode()); SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList; parseEHActions(EHActions, ActionList); assert(!ActionList.empty()); CurState += ActionList.size(); State += ActionList.size() - 1; // Remember all the __except block targets. for (auto &Handler : ActionList) { if (auto *CH = dyn_cast<CatchHandler>(Handler.get())) { auto *BA = cast<BlockAddress>(CH->getHandlerBlockOrFunc()); #ifndef NDEBUG for (BasicBlock *Pred : predecessors(BA->getBasicBlock())) assert(Pred->isLandingPad() && "WinEHPrepare failed to split block"); #endif ExceptBlocks.insert(BA->getBasicBlock()); } } } insertStateNumberStore(RegNode, II, State); } } } // Insert llvm.x86.seh.restoreframe() into each __except block. Function *RestoreFrame = Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe); for (BasicBlock *ExceptBB : ExceptBlocks) { IRBuilder<> Builder(ExceptBB->begin()); Builder.CreateCall(RestoreFrame, {}); } }