1 | //===- CFGBuilder.h - CFG building and updating utility ----------*- 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 | /// \file |
9 | /// CFGBuilders provides utilities fo building and updating CFG for testing |
10 | /// purposes. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_UNITTESTS_CFG_BUILDER_H |
15 | #define LLVM_UNITTESTS_CFG_BUILDER_H |
16 | |
17 | #include "llvm/ADT/StringMap.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/Support/Debug.h" |
20 | |
21 | #include <memory> |
22 | #include <optional> |
23 | #include <set> |
24 | #include <tuple> |
25 | #include <vector> |
26 | |
27 | namespace llvm { |
28 | |
29 | class LLVMContext; |
30 | class Module; |
31 | class Function; |
32 | class BasicBlock; |
33 | class raw_ostream; |
34 | |
35 | struct CFGHolder { |
36 | std::unique_ptr<LLVMContext> Context; |
37 | std::unique_ptr<Module> M; |
38 | Function *F; |
39 | |
40 | CFGHolder(StringRef ModuleName = "m" , StringRef FunctionName = "foo" ); |
41 | ~CFGHolder(); // Defined in the .cpp file so we can use forward declarations. |
42 | }; |
43 | |
44 | /// \brief |
45 | /// CFGBuilder builds IR with specific CFG, based on the supplied list of arcs. |
46 | /// It's able to apply the provided updates and automatically modify the IR. |
47 | /// |
48 | /// Internally it makes every basic block end with either SwitchInst or with |
49 | /// UnreachableInst. When all arc to a BB are deleted, the BB remains in the |
50 | /// function and doesn't get deleted. |
51 | /// |
52 | class CFGBuilder { |
53 | public: |
54 | struct Arc { |
55 | StringRef From; |
56 | StringRef To; |
57 | |
58 | friend bool operator<(const Arc &LHS, const Arc &RHS) { |
59 | return std::tie(args: LHS.From, args: LHS.To) < |
60 | std::tie(args: RHS.From, args: RHS.To); |
61 | } |
62 | }; |
63 | |
64 | enum class ActionKind { Insert, Delete }; |
65 | struct Update { |
66 | ActionKind Action; |
67 | Arc Edge; |
68 | }; |
69 | |
70 | CFGBuilder(Function *F, const std::vector<Arc> &InitialArcs, |
71 | std::vector<Update> Updates); |
72 | |
73 | BasicBlock *getOrAddBlock(StringRef BlockName); |
74 | std::optional<Update> getNextUpdate() const; |
75 | std::optional<Update> applyUpdate(); |
76 | void dump(raw_ostream &OS = dbgs()) const; |
77 | |
78 | private: |
79 | void buildCFG(const std::vector<Arc> &Arcs); |
80 | bool connect(const Arc &A); |
81 | bool disconnect(const Arc &A); |
82 | |
83 | Function *F; |
84 | unsigned UpdateIdx = 0; |
85 | StringMap<BasicBlock *> NameToBlock; |
86 | std::set<Arc> Arcs; |
87 | std::vector<Update> Updates; |
88 | }; |
89 | |
90 | } // namespace llvm |
91 | |
92 | #endif |
93 | |