1 //===-- Analysis/EHUtils.h - Exception handling related utils --*-//C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 8 #ifndef LLVM_ANALYSIS_EHUTILS_H 9 #define LLVM_ANALYSIS_EHUTILS_H 10 11 #include "llvm/ADT/DenseMap.h" 12 #include "llvm/ADT/DenseSet.h" 13 14 namespace llvm { 15 16 /// Compute a list of blocks that are only reachable via EH paths. 17 template <typename FunctionT, typename BlockT> 18 static void computeEHOnlyBlocks(FunctionT &F, DenseSet<BlockT *> &EHBlocks) { 19 // A block can be unknown if its not reachable from anywhere 20 // EH if its only reachable from start blocks via some path through EH pads 21 // NonEH if it's reachable from Non EH blocks as well. 22 enum Status { Unknown = 0, EH = 1, NonEH = 2 }; 23 DenseSet<BlockT *> WorkList; 24 DenseMap<BlockT *, Status> Statuses; 25 26 auto GetStatus = [&](BlockT *BB) { 27 auto It = Statuses.find(BB); 28 return It != Statuses.end() ? It->second : Unknown; 29 }; 30 31 auto CheckPredecessors = [&](BlockT *BB, Status Stat) { 32 for (auto *PredBB : predecessors(BB)) { 33 Status PredStatus = GetStatus(PredBB); 34 // If status of predecessor block has gone above current block 35 // we update current blocks status. 36 if (PredStatus > Stat) 37 Stat = PredStatus; 38 } 39 return Stat; 40 }; 41 42 auto AddSuccesors = [&](BlockT *BB) { 43 for (auto *SuccBB : successors(BB)) { 44 if (!SuccBB->isEHPad()) 45 WorkList.insert(SuccBB); 46 } 47 }; 48 49 // Insert the successors of start block and landing pads successor. 50 BlockT *StartBlock = &F.front(); 51 Statuses[StartBlock] = NonEH; 52 AddSuccesors(StartBlock); 53 54 for (auto &BB : F) { 55 if (BB.isEHPad()) { 56 AddSuccesors(&BB); 57 Statuses[&BB] = EH; 58 } 59 } 60 61 // Worklist iterative algorithm. 62 while (!WorkList.empty()) { 63 auto *BB = *WorkList.begin(); 64 WorkList.erase(BB); 65 66 Status OldStatus = GetStatus(BB); 67 68 // Check on predecessors and check for 69 // Status update. 70 Status NewStatus = CheckPredecessors(BB, OldStatus); 71 72 // Did the block status change? 73 bool Changed = OldStatus != NewStatus; 74 if (Changed) { 75 AddSuccesors(BB); 76 Statuses[BB] = NewStatus; 77 } 78 } 79 80 for (auto Entry : Statuses) { 81 if (Entry.second == EH) 82 EHBlocks.insert(Entry.first); 83 } 84 } 85 } // namespace llvm 86 87 #endif 88