Coverage Report

Created: 2023-10-30 17:15

/builds/2mk6rsew/0/parcoach/parcoach/src/aSSA/PTACallGraph.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "PTACallGraph.h"
2
#include "parcoach/andersen/Andersen.h"
3
4
#include "llvm/IR/Instructions.h"
5
#include "llvm/IR/Module.h"
6
7
#include <memory>
8
#include <queue>
9
10
using namespace llvm;
11
12
AnalysisKey PTACallGraphAnalysis::Key;
13
PTACallGraphAnalysis::Result
14
1.76k
PTACallGraphAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
15
1.76k
  TimeTraceScope TTS("PTACallGraphAnalysis");
16
1.76k
  Andersen const &AA = AM.getResult<AndersenAA>(M);
17
1.76k
  return std::make_unique<PTACallGraph>(M, AA);
18
1.76k
}
19
20
PTACallGraph::PTACallGraph(llvm::Module const &M, Andersen const &AA)
21
    : AA(AA), Root(nullptr), ProgEntry(nullptr),
22
      ExternalCallingNode(getOrInsertFunction(nullptr)),
23
1.76k
      CallsExternalNode(std::make_unique<PTACallGraphNode>(nullptr)) {
24
25
1.76k
  TimeTraceScope TTS("PTACallGraph");
26
19.8k
  for (Function const &F : M) {
27
19.8k
    addToCallGraph(F);
28
19.8k
  }
29
30
1.76k
  if (!Root) {
31
5
    Root = ExternalCallingNode;
32
5
  }
33
34
1.76k
  if (!ProgEntry) {
35
5
    errs() << "Warning: no main function in module\n";
36
1.75k
  } else {
37
    // Compute reachable functions from main
38
1.75k
    std::queue<PTACallGraphNode *> ToVisit;
39
1.75k
    std::set<PTACallGraphNode *> Visited;
40
41
1.75k
    ToVisit.push(ProgEntry);
42
1.75k
    Visited.insert(ProgEntry);
43
44
21.4k
    while (!ToVisit.empty()) {
45
19.6k
      PTACallGraphNode *N = ToVisit.front();
46
19.6k
      ToVisit.pop();
47
48
19.6k
      Function *F = N->getFunction();
49
19.6k
      if (F) {
50
17.9k
        reachableFunctions.insert(F);
51
17.9k
      }
52
53
63.2k
      for (auto I = N->begin(), E = N->end(); I != E; ++I) {
54
43.5k
        PTACallGraphNode *CalleeNode = I->second;
55
43.5k
        assert(CalleeNode);
56
43.5k
        if (Visited.find(CalleeNode) == Visited.end()) {
57
17.9k
          Visited.insert(CalleeNode);
58
17.9k
          ToVisit.push(CalleeNode);
59
17.9k
        }
60
43.5k
      }
61
19.6k
    }
62
1.75k
  }
63
1.76k
}
64
65
1.76k
PTACallGraph::~PTACallGraph() {
66
  // TODO
67
1.76k
}
68
69
19.8k
void PTACallGraph::addToCallGraph(Function const &F) {
70
19.8k
  PTACallGraphNode *Node = getOrInsertFunction(&F);
71
72
  // If this function has external linkage, anything could call it.
73
19.8k
  if (!F.hasLocalLinkage()) {
74
19.8k
    ExternalCallingNode->addCalledFunction(nullptr, Node);
75
76
    // Found the entry point?
77
19.8k
    if (F.getName() == "main") {
78
1.75k
      assert(!Root && "there should be at most one main");
79
1.75k
      Root = Node; // Found a main, keep track of it!
80
81
1.75k
      ProgEntry = Node;
82
1.75k
    }
83
19.8k
  }
84
85
  // If this function has its address taken, anything could call it.
86
19.8k
  if (F.hasAddressTaken()) {
87
9
    ExternalCallingNode->addCalledFunction(nullptr, Node);
88
9
  }
89
90
  // If this function is not defined in this translation unit, it could call
91
  // anything.
92
19.8k
  if (F.isDeclaration() && !F.isIntrinsic()) {
93
16.1k
    Node->addCalledFunction(nullptr, CallsExternalNode.get());
94
16.1k
  }
95
96
  // Look for calls by this function.
97
19.8k
  for (BasicBlock const &BB : F) {
98
189k
    for (Instruction const &I : BB) {
99
189k
      if (auto const *CI = dyn_cast<CallInst>(&I)) {
100
54.2k
        Function const *Callee = CI->getCalledFunction();
101
102
54.2k
        if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID())) {
103
          // Indirect calls of intrinsics are not allowed so no need to check.
104
          // We can be more precise here by using TargetArg returned by
105
          // Intrinsic::isLeaf.
106
3
          Node->addCalledFunction(CI, CallsExternalNode.get());
107
54.2k
        } else if (!Callee->isIntrinsic()) {
108
27.4k
          Node->addCalledFunction(CI, getOrInsertFunction(Callee));
109
27.4k
        }
110
111
        // Indirect calls
112
54.2k
        if (!Callee) {
113
3
          Value const *CalledValue =
114
3
              CI->getCalledOperand(); // CI.getCalledValue();
115
3
          assert(CalledValue);
116
117
3
          std::vector<Value const *> PtsSet;
118
119
3
          bool Found = AA.getPointsToSet(CalledValue, PtsSet);
120
3
          assert(Found && "coult not compute points to set for call inst");
121
122
3
          Found = false;
123
6
          auto IsCandidateF = [&](Value const *V) {
124
6
            const auto *CandidateF = dyn_cast<Function>(V);
125
6
            if (!CandidateF) {
126
0
              return false;
127
0
            }
128
6
            return (CI->arg_size() == CandidateF->arg_size() ||
129
6
                    (CandidateF->isVarArg() &&
130
2
                     CI->arg_size() > CandidateF->arg_size()));
131
6
          };
132
6
          for (Value const *V : make_filter_range(PtsSet, IsCandidateF)) {
133
6
            auto const *LocalCallee = cast<Function>(V);
134
6
            Found = true;
135
136
6
            indirectCallMap[CI].insert(LocalCallee);
137
138
6
            if (Intrinsic::isLeaf(LocalCallee->getIntrinsicID())) {
139
6
              Node->addCalledFunction(CI, getOrInsertFunction(LocalCallee));
140
6
            }
141
6
          }
142
3
          assert(Found && "could not find called function for call inst");
143
3
          (void)Found;
144
3
        }
145
54.2k
      }
146
189k
    }
147
15.2k
  }
148
19.8k
}
149
150
94.0k
bool PTACallGraph::isReachableFromEntry(Function const &F) const {
151
94.0k
  if (ProgEntry) {
152
94.0k
    return reachableFunctions.find(&F) != reachableFunctions.end();
153
94.0k
  }
154
33
  return true;
155
94.0k
}
156
157
49.0k
PTACallGraphNode *PTACallGraph::getOrInsertFunction(llvm::Function const *F) {
158
49.0k
  auto &CGN = FunctionMap[F];
159
49.0k
  if (CGN) {
160
27.4k
    return CGN.get();
161
27.4k
  }
162
163
21.6k
  CGN = std::make_unique<PTACallGraphNode>(const_cast<Function *>(F));
164
  // LLVM10: CGN = std::make_unique<PTACallGraphNode>(const_cast<Function
165
  // *>(F));
166
21.6k
  return CGN.get();
167
49.0k
}
168
169
void PTACallGraphNode::addCalledFunction(CallBase const *CB,
170
63.4k
                                         PTACallGraphNode *M) {
171
63.4k
  CalledFunctions.emplace_back(CB, M);
172
63.4k
}