/src/hermes/include/hermes/BCGen/Exceptions.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) Meta Platforms, Inc. and affiliates. |
3 | | * |
4 | | * This source code is licensed under the MIT license found in the |
5 | | * LICENSE file in the root directory of this source tree. |
6 | | */ |
7 | | |
8 | | #ifndef HERMES_BCGEN_EXCEPTIONS_H |
9 | | #define HERMES_BCGEN_EXCEPTIONS_H |
10 | | |
11 | | #include "llvh/ADT/DenseMap.h" |
12 | | #include "llvh/ADT/SmallPtrSet.h" |
13 | | #include "llvh/ADT/SmallVector.h" |
14 | | |
15 | | namespace hermes { |
16 | | |
17 | | class BasicBlock; |
18 | | class Function; |
19 | | class CatchInst; |
20 | | |
21 | | /// Maps catch instructions to the list of basic blocks that the catch covers |
22 | | /// and other metadata that's needed for code generation of the catch |
23 | | /// instruction. |
24 | | class CatchCoverageInfo { |
25 | | public: |
26 | | /// The bytecode location of the catch instruction. |
27 | | int catchLocation{0}; |
28 | | |
29 | | /// The list of basic blocks covered by this catch. |
30 | | llvh::SmallVector<BasicBlock *, 8> coveredBlockList{}; |
31 | | |
32 | | /// The depth of this catch in nesting. |
33 | | unsigned depth{0}; |
34 | | |
35 | 1.64k | explicit CatchCoverageInfo(int location) : catchLocation{location} {} |
36 | 1.64k | explicit CatchCoverageInfo() = default; |
37 | | }; |
38 | | |
39 | | //===----------------------------------------------------------------------===// |
40 | | // Exception Handler Data Structure |
41 | | //===----------------------------------------------------------------------===// |
42 | | struct ExceptionHandlerInfo { |
43 | | uint32_t start; |
44 | | uint32_t end; |
45 | | uint32_t target; |
46 | | uint32_t depth; |
47 | | |
48 | | /// We want to keep deeper ranges to show up earlier, but we also want to |
49 | | /// sort all handlers reproducibly. |
50 | 12.9k | bool operator<(const ExceptionHandlerInfo &rhs) const { |
51 | 12.9k | assert( |
52 | 12.9k | (this == &rhs || depth != rhs.depth || start != rhs.start) && |
53 | 12.9k | "two handlers with equal depth and start"); |
54 | 12.9k | return depth > rhs.depth || (depth == rhs.depth && start < rhs.start); |
55 | 12.9k | } |
56 | | }; |
57 | | |
58 | | /// Maps catch instructions to the basic blocks it covers. |
59 | | using CatchInfoMap = llvh::DenseMap<CatchInst *, CatchCoverageInfo>; |
60 | | |
61 | | //// Maps a basic block to it's beginning and end location in the bytecode. |
62 | | using BasicBlockInfoMap = |
63 | | llvh::DenseMap<BasicBlock *, std::pair<uint32_t, uint32_t>>; |
64 | | |
65 | | /// A list of exception handler table entries. |
66 | | using ExceptionEntryList = llvh::SmallVector<ExceptionHandlerInfo, 4>; |
67 | | |
68 | | /// Construct the list of basic blocks covered by each catch instruction. |
69 | | /// \return A set of blocks corresponding to the blocks that end a try starting |
70 | | /// at currentBlock on success. On failure, return None. |
71 | | /// \p F the function under consideration |
72 | | /// \p catchInfoMap a CatchInfoMap that has entries for every CatchInst |
73 | | /// \p aliveCatches the currently active CatchInsts (should be empty) |
74 | | /// \p visited the previously visited BasicBlocks (should be empty) |
75 | | /// \p currentBlock the entry BasicBlock |
76 | | /// \p maxRecursionDepth if the construction exceeds this many levels of |
77 | | /// recursion, it adds a compilation error and returns None. |
78 | | llvh::Optional<llvh::SmallPtrSet<BasicBlock *, 4>> constructCatchMap( |
79 | | Function *F, |
80 | | CatchInfoMap &catchInfoMap, |
81 | | llvh::SmallVectorImpl<CatchInst *> &aliveCatches, |
82 | | llvh::SmallPtrSetImpl<BasicBlock *> &visited, |
83 | | BasicBlock *startBlock, |
84 | | uint32_t maxRecursionDepth); |
85 | | |
86 | | /// Note: Returns an empty list if generation fails due to excessive recursion. |
87 | | ExceptionEntryList generateExceptionHandlers( |
88 | | CatchInfoMap &catchInfoMap, |
89 | | BasicBlockInfoMap &bbMap, |
90 | | Function *F); |
91 | | |
92 | | } // namespace hermes |
93 | | |
94 | | #endif |