//===-- Analysis/EHUtils.h - Exception handling related utils --*-//C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // #ifndef LLVM_ANALYSIS_EHUTILS_H #define LLVM_ANALYSIS_EHUTILS_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" namespace llvm { /// Compute a list of blocks that are only reachable via EH paths. template static void computeEHOnlyBlocks(FunctionT &F, DenseSet &EHBlocks) { // A block can be unknown if its not reachable from anywhere // EH if its only reachable from start blocks via some path through EH pads // NonEH if it's reachable from Non EH blocks as well. enum Status { Unknown = 0, EH = 1, NonEH = 2 }; DenseSet WorkList; DenseMap Statuses; auto GetStatus = [&](BlockT *BB) { if (Statuses.contains(BB)) return Statuses[BB]; else return Unknown; }; auto CheckPredecessors = [&](BlockT *BB, Status Stat) { for (auto *PredBB : predecessors(BB)) { Status PredStatus = GetStatus(PredBB); // If status of predecessor block has gone above current block // we update current blocks status. if (PredStatus > Stat) Stat = PredStatus; } return Stat; }; auto AddSuccesors = [&](BlockT *BB) { for (auto *SuccBB : successors(BB)) { if (!SuccBB->isEHPad()) WorkList.insert(SuccBB); } }; // Insert the successors of start block and landing pads successor. BlockT *StartBlock = &F.front(); Statuses[StartBlock] = NonEH; AddSuccesors(StartBlock); for (auto &BB : F) { if (BB.isEHPad()) { AddSuccesors(&BB); Statuses[&BB] = EH; } } // Worklist iterative algorithm. while (!WorkList.empty()) { auto *BB = *WorkList.begin(); WorkList.erase(BB); Status OldStatus = GetStatus(BB); // Check on predecessors and check for // Status update. Status NewStatus = CheckPredecessors(BB, OldStatus); // Did the block status change? bool Changed = OldStatus != NewStatus; if (Changed) { AddSuccesors(BB); Statuses[BB] = NewStatus; } } EHBlocks.clear(); for (auto Entry : Statuses) { if (Entry.second == EH) EHBlocks.insert(Entry.first); } } } // namespace llvm #endif