File indexing completed on 2026-05-10 08:43:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 #ifndef LLVM_ANALYSIS_CALLGRAPH_H
0046 #define LLVM_ANALYSIS_CALLGRAPH_H
0047
0048 #include "llvm/IR/InstrTypes.h"
0049 #include "llvm/IR/PassManager.h"
0050 #include "llvm/IR/ValueHandle.h"
0051 #include "llvm/Pass.h"
0052 #include <cassert>
0053 #include <map>
0054 #include <memory>
0055 #include <utility>
0056 #include <vector>
0057
0058 namespace llvm {
0059
0060 template <class GraphType> struct GraphTraits;
0061 class CallGraphNode;
0062 class Function;
0063 class Module;
0064 class raw_ostream;
0065
0066
0067
0068
0069
0070
0071 class CallGraph {
0072 Module &M;
0073
0074 using FunctionMapTy =
0075 std::map<const Function *, std::unique_ptr<CallGraphNode>>;
0076
0077
0078 FunctionMapTy FunctionMap;
0079
0080
0081
0082 CallGraphNode *ExternalCallingNode;
0083
0084
0085
0086 std::unique_ptr<CallGraphNode> CallsExternalNode;
0087
0088 public:
0089 explicit CallGraph(Module &M);
0090 CallGraph(CallGraph &&Arg);
0091 ~CallGraph();
0092
0093 void print(raw_ostream &OS) const;
0094 void dump() const;
0095
0096 using iterator = FunctionMapTy::iterator;
0097 using const_iterator = FunctionMapTy::const_iterator;
0098
0099
0100 Module &getModule() const { return M; }
0101
0102 bool invalidate(Module &, const PreservedAnalyses &PA,
0103 ModuleAnalysisManager::Invalidator &);
0104
0105 inline iterator begin() { return FunctionMap.begin(); }
0106 inline iterator end() { return FunctionMap.end(); }
0107 inline const_iterator begin() const { return FunctionMap.begin(); }
0108 inline const_iterator end() const { return FunctionMap.end(); }
0109
0110
0111 inline const CallGraphNode *operator[](const Function *F) const {
0112 const_iterator I = FunctionMap.find(F);
0113 assert(I != FunctionMap.end() && "Function not in callgraph!");
0114 return I->second.get();
0115 }
0116
0117
0118 inline CallGraphNode *operator[](const Function *F) {
0119 const_iterator I = FunctionMap.find(F);
0120 assert(I != FunctionMap.end() && "Function not in callgraph!");
0121 return I->second.get();
0122 }
0123
0124
0125
0126 CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; }
0127
0128 CallGraphNode *getCallsExternalNode() const {
0129 return CallsExternalNode.get();
0130 }
0131
0132
0133
0134 void ReplaceExternalCallEdge(CallGraphNode *Old, CallGraphNode *New);
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 Function *removeFunctionFromModule(CallGraphNode *CGN);
0148
0149
0150
0151 CallGraphNode *getOrInsertFunction(const Function *F);
0152
0153
0154 void populateCallGraphNode(CallGraphNode *CGN);
0155
0156
0157
0158 void addToCallGraph(Function *F);
0159 };
0160
0161
0162
0163
0164
0165 class CallGraphNode {
0166 public:
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 using CallRecord = std::pair<std::optional<WeakTrackingVH>, CallGraphNode *>;
0178
0179 public:
0180 using CalledFunctionsVector = std::vector<CallRecord>;
0181
0182
0183 inline CallGraphNode(CallGraph *CG, Function *F) : CG(CG), F(F) {}
0184
0185 CallGraphNode(const CallGraphNode &) = delete;
0186 CallGraphNode &operator=(const CallGraphNode &) = delete;
0187
0188 ~CallGraphNode() {
0189 assert(NumReferences == 0 && "Node deleted while references remain");
0190 }
0191
0192 using iterator = std::vector<CallRecord>::iterator;
0193 using const_iterator = std::vector<CallRecord>::const_iterator;
0194
0195
0196 Function *getFunction() const { return F; }
0197
0198 inline iterator begin() { return CalledFunctions.begin(); }
0199 inline iterator end() { return CalledFunctions.end(); }
0200 inline const_iterator begin() const { return CalledFunctions.begin(); }
0201 inline const_iterator end() const { return CalledFunctions.end(); }
0202 inline bool empty() const { return CalledFunctions.empty(); }
0203 inline unsigned size() const { return (unsigned)CalledFunctions.size(); }
0204
0205
0206
0207 unsigned getNumReferences() const { return NumReferences; }
0208
0209
0210 CallGraphNode *operator[](unsigned i) const {
0211 assert(i < CalledFunctions.size() && "Invalid index");
0212 return CalledFunctions[i].second;
0213 }
0214
0215
0216 void dump() const;
0217 void print(raw_ostream &OS) const;
0218
0219
0220
0221
0222
0223
0224
0225
0226 void removeAllCalledFunctions() {
0227 while (!CalledFunctions.empty()) {
0228 CalledFunctions.back().second->DropRef();
0229 CalledFunctions.pop_back();
0230 }
0231 }
0232
0233
0234 void stealCalledFunctionsFrom(CallGraphNode *N) {
0235 assert(CalledFunctions.empty() &&
0236 "Cannot steal callsite information if I already have some");
0237 std::swap(CalledFunctions, N->CalledFunctions);
0238 }
0239
0240
0241 void addCalledFunction(CallBase *Call, CallGraphNode *M) {
0242 CalledFunctions.emplace_back(Call ? std::optional<WeakTrackingVH>(Call)
0243 : std::optional<WeakTrackingVH>(),
0244 M);
0245 M->AddRef();
0246 }
0247
0248 void removeCallEdge(iterator I) {
0249 I->second->DropRef();
0250 *I = CalledFunctions.back();
0251 CalledFunctions.pop_back();
0252 }
0253
0254
0255
0256
0257 void removeCallEdgeFor(CallBase &Call);
0258
0259
0260
0261
0262
0263
0264 void removeAnyCallEdgeTo(CallGraphNode *Callee);
0265
0266
0267
0268 void removeOneAbstractEdgeTo(CallGraphNode *Callee);
0269
0270
0271
0272
0273
0274 void replaceCallEdge(CallBase &Call, CallBase &NewCall,
0275 CallGraphNode *NewNode);
0276
0277 private:
0278 friend class CallGraph;
0279
0280 CallGraph *CG;
0281 Function *F;
0282
0283 std::vector<CallRecord> CalledFunctions;
0284
0285
0286
0287 unsigned NumReferences = 0;
0288
0289 void DropRef() { --NumReferences; }
0290 void AddRef() { ++NumReferences; }
0291
0292
0293 void allReferencesDropped() { NumReferences = 0; }
0294 };
0295
0296
0297
0298
0299
0300
0301 class CallGraphAnalysis : public AnalysisInfoMixin<CallGraphAnalysis> {
0302 friend AnalysisInfoMixin<CallGraphAnalysis>;
0303
0304 static AnalysisKey Key;
0305
0306 public:
0307
0308 using Result = CallGraph;
0309
0310
0311
0312
0313 CallGraph run(Module &M, ModuleAnalysisManager &) { return CallGraph(M); }
0314 };
0315
0316
0317 class CallGraphPrinterPass : public PassInfoMixin<CallGraphPrinterPass> {
0318 raw_ostream &OS;
0319
0320 public:
0321 explicit CallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}
0322
0323 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
0324
0325 static bool isRequired() { return true; }
0326 };
0327
0328
0329 class CallGraphSCCsPrinterPass
0330 : public PassInfoMixin<CallGraphSCCsPrinterPass> {
0331 raw_ostream &OS;
0332
0333 public:
0334 explicit CallGraphSCCsPrinterPass(raw_ostream &OS) : OS(OS) {}
0335
0336 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
0337
0338 static bool isRequired() { return true; }
0339 };
0340
0341
0342
0343
0344
0345
0346
0347
0348 class CallGraphWrapperPass : public ModulePass {
0349 std::unique_ptr<CallGraph> G;
0350
0351 public:
0352 static char ID;
0353
0354 CallGraphWrapperPass();
0355 ~CallGraphWrapperPass() override;
0356
0357
0358
0359 const CallGraph &getCallGraph() const { return *G; }
0360 CallGraph &getCallGraph() { return *G; }
0361
0362 using iterator = CallGraph::iterator;
0363 using const_iterator = CallGraph::const_iterator;
0364
0365
0366 Module &getModule() const { return G->getModule(); }
0367
0368 inline iterator begin() { return G->begin(); }
0369 inline iterator end() { return G->end(); }
0370 inline const_iterator begin() const { return G->begin(); }
0371 inline const_iterator end() const { return G->end(); }
0372
0373
0374 inline const CallGraphNode *operator[](const Function *F) const {
0375 return (*G)[F];
0376 }
0377
0378
0379 inline CallGraphNode *operator[](const Function *F) { return (*G)[F]; }
0380
0381
0382
0383 CallGraphNode *getExternalCallingNode() const {
0384 return G->getExternalCallingNode();
0385 }
0386
0387 CallGraphNode *getCallsExternalNode() const {
0388 return G->getCallsExternalNode();
0389 }
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402 Function *removeFunctionFromModule(CallGraphNode *CGN) {
0403 return G->removeFunctionFromModule(CGN);
0404 }
0405
0406
0407
0408 CallGraphNode *getOrInsertFunction(const Function *F) {
0409 return G->getOrInsertFunction(F);
0410 }
0411
0412
0413
0414
0415
0416 void getAnalysisUsage(AnalysisUsage &AU) const override;
0417 bool runOnModule(Module &M) override;
0418 void releaseMemory() override;
0419
0420 void print(raw_ostream &o, const Module *) const override;
0421 void dump() const;
0422 };
0423
0424
0425
0426
0427
0428
0429
0430
0431 template <> struct GraphTraits<CallGraphNode *> {
0432 using NodeRef = CallGraphNode *;
0433 using CGNPairTy = CallGraphNode::CallRecord;
0434
0435 static NodeRef getEntryNode(CallGraphNode *CGN) { return CGN; }
0436 static CallGraphNode *CGNGetValue(CGNPairTy P) { return P.second; }
0437
0438 using ChildIteratorType =
0439 mapped_iterator<CallGraphNode::iterator, decltype(&CGNGetValue)>;
0440
0441 static ChildIteratorType child_begin(NodeRef N) {
0442 return ChildIteratorType(N->begin(), &CGNGetValue);
0443 }
0444
0445 static ChildIteratorType child_end(NodeRef N) {
0446 return ChildIteratorType(N->end(), &CGNGetValue);
0447 }
0448 };
0449
0450 template <> struct GraphTraits<const CallGraphNode *> {
0451 using NodeRef = const CallGraphNode *;
0452 using CGNPairTy = CallGraphNode::CallRecord;
0453 using EdgeRef = const CallGraphNode::CallRecord &;
0454
0455 static NodeRef getEntryNode(const CallGraphNode *CGN) { return CGN; }
0456 static const CallGraphNode *CGNGetValue(CGNPairTy P) { return P.second; }
0457
0458 using ChildIteratorType =
0459 mapped_iterator<CallGraphNode::const_iterator, decltype(&CGNGetValue)>;
0460 using ChildEdgeIteratorType = CallGraphNode::const_iterator;
0461
0462 static ChildIteratorType child_begin(NodeRef N) {
0463 return ChildIteratorType(N->begin(), &CGNGetValue);
0464 }
0465
0466 static ChildIteratorType child_end(NodeRef N) {
0467 return ChildIteratorType(N->end(), &CGNGetValue);
0468 }
0469
0470 static ChildEdgeIteratorType child_edge_begin(NodeRef N) {
0471 return N->begin();
0472 }
0473 static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); }
0474
0475 static NodeRef edge_dest(EdgeRef E) { return E.second; }
0476 };
0477
0478 template <>
0479 struct GraphTraits<CallGraph *> : public GraphTraits<CallGraphNode *> {
0480 using PairTy =
0481 std::pair<const Function *const, std::unique_ptr<CallGraphNode>>;
0482
0483 static NodeRef getEntryNode(CallGraph *CGN) {
0484 return CGN->getExternalCallingNode();
0485 }
0486
0487 static CallGraphNode *CGGetValuePtr(const PairTy &P) {
0488 return P.second.get();
0489 }
0490
0491
0492 using nodes_iterator =
0493 mapped_iterator<CallGraph::iterator, decltype(&CGGetValuePtr)>;
0494
0495 static nodes_iterator nodes_begin(CallGraph *CG) {
0496 return nodes_iterator(CG->begin(), &CGGetValuePtr);
0497 }
0498
0499 static nodes_iterator nodes_end(CallGraph *CG) {
0500 return nodes_iterator(CG->end(), &CGGetValuePtr);
0501 }
0502 };
0503
0504 template <>
0505 struct GraphTraits<const CallGraph *> : public GraphTraits<
0506 const CallGraphNode *> {
0507 using PairTy =
0508 std::pair<const Function *const, std::unique_ptr<CallGraphNode>>;
0509
0510 static NodeRef getEntryNode(const CallGraph *CGN) {
0511 return CGN->getExternalCallingNode();
0512 }
0513
0514 static const CallGraphNode *CGGetValuePtr(const PairTy &P) {
0515 return P.second.get();
0516 }
0517
0518
0519 using nodes_iterator =
0520 mapped_iterator<CallGraph::const_iterator, decltype(&CGGetValuePtr)>;
0521
0522 static nodes_iterator nodes_begin(const CallGraph *CG) {
0523 return nodes_iterator(CG->begin(), &CGGetValuePtr);
0524 }
0525
0526 static nodes_iterator nodes_end(const CallGraph *CG) {
0527 return nodes_iterator(CG->end(), &CGGetValuePtr);
0528 }
0529 };
0530
0531 }
0532
0533 #endif