/builds/2mk6rsew/0/parcoach/parcoach/src/aSSA/PTACallGraph.h
Line | Count | Source |
1 | | #ifndef PTACALLGRAPH_H |
2 | | #define PTACALLGRAPH_H |
3 | | |
4 | | #include "llvm/ADT/GraphTraits.h" |
5 | | #include "llvm/ADT/STLExtras.h" |
6 | | #include "llvm/IR/Intrinsics.h" |
7 | | #include "llvm/IR/ValueHandle.h" |
8 | | #include "llvm/IR/ValueMap.h" |
9 | | #include "llvm/Passes/PassBuilder.h" |
10 | | |
11 | | #include <map> |
12 | | #include <set> |
13 | | |
14 | | namespace llvm { |
15 | | class CallBase; |
16 | | class Function; |
17 | | class Module; |
18 | | } // namespace llvm |
19 | | class PTACallGraphNode; |
20 | | class Andersen; |
21 | | |
22 | | class PTACallGraphNode { |
23 | | public: |
24 | | using CallRecord = std::pair<llvm::CallBase const *, PTACallGraphNode *>; |
25 | | |
26 | | using CalledFunctionsVector = std::vector<CallRecord>; |
27 | | |
28 | 23.3k | inline PTACallGraphNode(llvm::Function *F) : F(F) {} |
29 | | |
30 | 23.3k | ~PTACallGraphNode() {} |
31 | | |
32 | | using iterator = std::vector<CallRecord>::iterator; |
33 | | using const_iterator = std::vector<CallRecord>::const_iterator; |
34 | | |
35 | | /// \brief Returns the function that this call graph node represents. |
36 | 434k | llvm::Function *getFunction() const { return F; } |
37 | | |
38 | 179k | inline const_iterator begin() const { return CalledFunctions.begin(); } |
39 | 370k | inline const_iterator end() const { return CalledFunctions.end(); } |
40 | | |
41 | | /// \brief Adds a function to the list of functions called by this one. |
42 | | void addCalledFunction(llvm::CallBase const *CB, PTACallGraphNode *M); |
43 | | |
44 | | private: |
45 | | friend class PTACallGraph; |
46 | | |
47 | | llvm::AssertingVH<llvm::Function> F; |
48 | | |
49 | | std::vector<CallRecord> CalledFunctions; |
50 | | }; |
51 | | |
52 | | class PTACallGraph { |
53 | | public: |
54 | | using FunctionMapTy = |
55 | | std::map<llvm::Function const *, std::unique_ptr<PTACallGraphNode>>; |
56 | | using iterator = FunctionMapTy::iterator; |
57 | | using const_iterator = FunctionMapTy::const_iterator; |
58 | | |
59 | | private: |
60 | | Andersen const &AA; |
61 | | |
62 | | /// \brief A map from \c Function* to \c CallGraphNode*. |
63 | | FunctionMapTy FunctionMap; |
64 | | |
65 | | // Must be main |
66 | | PTACallGraphNode *Root; |
67 | | |
68 | | PTACallGraphNode *ProgEntry; |
69 | | |
70 | | std::set<llvm::Function const *> reachableFunctions; |
71 | | |
72 | | /// \brief This node has edges to all external functions and those internal |
73 | | /// functions that have their address taken. |
74 | | PTACallGraphNode *ExternalCallingNode; |
75 | | |
76 | | /// \brief This node has edges to it from all functions making indirect calls |
77 | | /// or calling an external function. |
78 | | std::unique_ptr<PTACallGraphNode> CallsExternalNode; |
79 | | |
80 | | /// \brief Add a function to the call graph, and link the node to all of the |
81 | | /// functions that it calls. |
82 | | void addToCallGraph(llvm::Function const &F); |
83 | | |
84 | | llvm::ValueMap<llvm::Instruction const *, std::set<llvm::Function const *>> |
85 | | indirectCallMap; |
86 | | |
87 | | PTACallGraphNode *getOrInsertFunction(llvm::Function const *F); |
88 | | |
89 | | public: |
90 | | explicit PTACallGraph(llvm::Module const &M, Andersen const &AA); |
91 | | ~PTACallGraph(); |
92 | | |
93 | 1.75k | PTACallGraphNode *getEntry() const { return Root; } |
94 | | |
95 | | /// \brief Returns the \c CallGraphNode which is used to represent |
96 | | /// undetermined calls into the callgraph. |
97 | 5.28k | PTACallGraphNode *getExternalCallingNode() const { |
98 | 5.28k | return ExternalCallingNode; |
99 | 5.28k | } |
100 | | |
101 | | bool isReachableFromEntry(llvm::Function const &F) const; |
102 | 28 | auto const &getIndirectCallMap() const { return indirectCallMap; } |
103 | | }; |
104 | | |
105 | | class PTACallGraphAnalysis |
106 | | : public llvm::AnalysisInfoMixin<PTACallGraphAnalysis> { |
107 | | friend llvm::AnalysisInfoMixin<PTACallGraphAnalysis>; |
108 | | static llvm::AnalysisKey Key; |
109 | | |
110 | | public: |
111 | | // We return a unique_ptr to ensure stability of the analysis' internal state. |
112 | | using Result = std::unique_ptr<PTACallGraph>; |
113 | | static Result run(llvm::Module &M, llvm::ModuleAnalysisManager &); |
114 | | }; |
115 | | |
116 | | //===----------------------------------------------------------------------===// |
117 | | // GraphTraits specializations for call graphs so that they can be treated as |
118 | | // graphs by the generic graph algorithms. |
119 | | // |
120 | | |
121 | | // Provide graph traits for tranversing call graphs using standard graph |
122 | | // traversals. |
123 | | |
124 | | namespace llvm { |
125 | | |
126 | | template <> struct GraphTraits<PTACallGraphNode const *> { |
127 | | using NodeType = const PTACallGraphNode; |
128 | | using NodeRef = NodeType *; |
129 | | |
130 | | using CGNPairTy = PTACallGraphNode::CallRecord; |
131 | | |
132 | 190k | static NodeRef CGNDeref(CGNPairTy P) { return P.second; } |
133 | | |
134 | | typedef mapped_iterator<NodeType::const_iterator, decltype(&CGNDeref)> |
135 | | ChildIteratorType; |
136 | | |
137 | 70.1k | static inline ChildIteratorType child_begin(NodeType *N) { |
138 | 70.1k | return map_iterator(N->begin(), CGNDeref); |
139 | 70.1k | } |
140 | 260k | static inline ChildIteratorType child_end(NodeType *N) { |
141 | 260k | return map_iterator(N->end(), CGNDeref); |
142 | 260k | } |
143 | | }; |
144 | | |
145 | | template <> |
146 | | struct GraphTraits<PTACallGraph const *> |
147 | | : public GraphTraits<PTACallGraphNode const *> { |
148 | 5.28k | static NodeType *getEntryNode(PTACallGraph const *CGN) { |
149 | 5.28k | return CGN->getExternalCallingNode(); // Start at the external node! |
150 | 5.28k | } |
151 | | }; |
152 | | } // namespace llvm |
153 | | |
154 | | #endif /* PTACALLGRAPH_H */ |