Coverage Report

Created: 2023-10-30 17:15

/builds/2mk6rsew/0/parcoach/parcoach/src/include/parcoach/DepGraphDCF.h
Line
Count
Source
1
#pragma once
2
3
#include "parcoach/MemorySSA.h"
4
5
#include "llvm/IR/InstVisitor.h"
6
7
#include <optional>
8
9
class PTACallGraphNode;
10
namespace llvm {
11
class raw_fd_ostream;
12
}
13
14
namespace parcoach {
15
16
class DepGraphDCF : public llvm::InstVisitor<DepGraphDCF> {
17
public:
18
  using VarSet = std::set<MSSAVar *>;
19
  using ConstVarSet = std::set<MSSAVar const *>;
20
  using ValueSet = std::set<llvm::Value const *>;
21
22
  DepGraphDCF(parcoach::MemorySSA *mssa, PTACallGraph const &CG,
23
              llvm::FunctionAnalysisManager &AM, llvm::Module &M,
24
              bool ContextInsensitive, bool noPtrDep = false,
25
              bool noPred = false, bool disablePhiElim = false);
26
  virtual ~DepGraphDCF();
27
28
  void toDot(llvm::StringRef filename) const;
29
  void dotTaintPath(llvm::Value const *v, llvm::StringRef filename,
30
                    llvm::Instruction const *collective) const;
31
32
  // FIXME: ideally we would have two classes: one analysis result, and one
33
  // visitor constructing this analysis result (so that the user can't "visit"
34
  // stuff manually and change the analysis' result).
35
  void visitBasicBlock(llvm::BasicBlock &BB);
36
  void visitAllocaInst(llvm::AllocaInst &I);
37
  void visitCmpInst(llvm::CmpInst &I);
38
  void visitFreezeInst(llvm::FreezeInst &I);
39
  void visitUnaryOperator(llvm::UnaryOperator &I);
40
  void visitLoadInst(llvm::LoadInst &I);
41
  void visitStoreInst(llvm::StoreInst &I);
42
  void visitGetElementPtrInst(llvm::GetElementPtrInst &I);
43
  void visitPHINode(llvm::PHINode &I);
44
  void visitCastInst(llvm::CastInst &I);
45
  void visitSelectInst(llvm::SelectInst &I);
46
  void visitBinaryOperator(llvm::BinaryOperator &I);
47
  void visitCallInst(llvm::CallInst &I);
48
  void visitExtractValueInst(llvm::ExtractValueInst &I);
49
  void visitExtractElementInst(llvm::ExtractElementInst &I);
50
  void visitInsertElementInst(llvm::InsertElementInst &I);
51
  void visitInsertValueInst(llvm::InsertValueInst &I);
52
  void visitShuffleVectorInst(llvm::ShuffleVectorInst &I);
53
  void visitTerminator(llvm::Instruction &I);
54
  static void visitInstruction(llvm::Instruction &I);
55
56
  bool isTaintedValue(llvm::Value const *v) const;
57
58
  void getCallInterIPDF(llvm::CallInst const *call,
59
                        std::set<llvm::BasicBlock const *> &ipdf) const;
60
61
private:
62
  void build();
63
  void buildFunction(llvm::Function const *F);
64
  // Phi elimination pass.
65
  // A ssa Phi function can be eliminated if its operands are equivalent.
66
  // In this case operands are merged into a single node and the phi is replaced
67
  // with this single node. The phi elimination pass allows us to break the
68
  // dependency with phi predicates when its operands are the same, e.g.:
69
  // if (rank)
70
  //   a = 0;
71
  // else
72
  //   a = 0;
73
  void phiElimination();
74
75
  void computeTaintedValuesContextInsensitive();
76
  void computeTaintedValuesContextSensitive();
77
  void computeTaintedValuesCSForEntry(PTACallGraphNode const *entry);
78
79
  parcoach::MemorySSA *mssa;
80
  PTACallGraph const &CG;
81
82
  llvm::Function const *curFunc;
83
  llvm::FunctionAnalysisManager &FAM;
84
  llvm::Module const &M;
85
  bool const ContextInsensitive;
86
  llvm::PostDominatorTree *PDT;
87
88
  /* Graph nodes */
89
90
  // Map from a function to all its top-level variables nodes.
91
  llvm::ValueMap<llvm::Function const *, ValueSet> funcToLLVMNodesMap;
92
  // Map from a function to all its address taken ssa nodes.
93
  llvm::ValueMap<llvm::Function const *, VarSet> funcToSSANodesMap;
94
  std::set<llvm::Function const *> varArgNodes;
95
96
  /* Graph edges */
97
98
  // top-level to top-level edges
99
  llvm::ValueMap<llvm::Value const *, ValueSet> llvmToLLVMChildren;
100
  llvm::ValueMap<llvm::Value const *, ValueSet> llvmToLLVMParents;
101
102
  // top-level to address-taken ssa edges
103
  llvm::ValueMap<llvm::Value const *, VarSet> llvmToSSAChildren;
104
  llvm::ValueMap<llvm::Value const *, VarSet> llvmToSSAParents;
105
  // address-taken ssa to top-level edges
106
  llvm::DenseMap<MSSAVar *, ValueSet> ssaToLLVMChildren;
107
  llvm::DenseMap<MSSAVar *, ValueSet> ssaToLLVMParents;
108
109
  // address-top ssa to address-taken ssa edges
110
  llvm::DenseMap<MSSAVar *, VarSet> ssaToSSAChildren;
111
  llvm::DenseMap<MSSAVar *, VarSet> ssaToSSAParents;
112
113
  static void enableMPI();
114
  static void enableOMP();
115
  static void enableUPC();
116
  static void enableCUDA();
117
118
  void addEdge(llvm::Value const *s, llvm::Value const *d);
119
  void addEdge(llvm::Value const *s, MSSAVar *d);
120
  void addEdge(MSSAVar *s, llvm::Value const *d);
121
  void addEdge(MSSAVar *s, MSSAVar *d);
122
  void removeEdge(llvm::Value const *s, llvm::Value const *d);
123
  void removeEdge(llvm::Value const *s, MSSAVar *d);
124
  void removeEdge(MSSAVar *s, llvm::Value const *d);
125
  void removeEdge(MSSAVar *s, MSSAVar *d);
126
127
  /* PDF+ call nodes and edges */
128
129
  // map from a function to all its call instructions
130
  llvm::ValueMap<llvm::Function const *, ValueSet> funcToCallNodes;
131
  // map from call instructions to called functions
132
  llvm::ValueMap<llvm::Value const *, llvm::Function const *> callToFuncEdges;
133
  // map from a condition to call instructions depending on that condition.
134
  llvm::ValueMap<llvm::Value const *, ValueSet> condToCallEdges;
135
136
  // map from a function to all the call sites calling this function.
137
  llvm::ValueMap<llvm::Function const *, ValueSet> funcToCallSites;
138
  // map from a callsite to all its conditions.
139
  llvm::ValueMap<llvm::Value const *, ValueSet> callsiteToConds;
140
141
  /* tainted nodes */
142
  ValueSet taintedLLVMNodes;
143
  ConstVarSet taintedSSANodes;
144
145
  ConstVarSet taintResetSSANodes;
146
  ConstVarSet ssaSources;
147
  ValueSet valueSources;
148
149
  void floodFunction(llvm::Function const *F);
150
  void floodFunctionFromFunction(llvm::Function const *to,
151
                                 llvm::Function const *from);
152
  void resetFunctionTaint(llvm::Function const *F);
153
  void computeFunctionCSTaintedConds(llvm::Function const *F);
154
  ValueSet taintedConditions;
155
156
  /* Graph construction for call sites*/
157
  void connectCSMus(llvm::CallInst &I);
158
  void connectCSChis(llvm::CallInst &I);
159
  void connectCSEffectiveParameters(llvm::CallInst &I);
160
  void connectCSEffectiveParametersExt(llvm::CallInst &I,
161
                                       llvm::Function const *callee);
162
  void connectCSCalledReturnValue(llvm::CallInst &I);
163
  void connectCSRetChi(llvm::CallInst &I);
164
165
  // Two nodes are equivalent if they have exactly the same incoming and
166
  // outgoing edges and if none of them are phi nodes.
167
  bool areSSANodesEquivalent(MSSAVar *var1, MSSAVar *var2);
168
169
  // This function replaces phi with op1 and removes op2.
170
  void eliminatePhi(MSSAPhi *phi, std::vector<MSSAVar *> ops);
171
172
  void dotFunction(llvm::raw_fd_ostream &stream, llvm::Function const *F) const;
173
  void dotExtFunction(llvm::raw_fd_ostream &stream,
174
                      llvm::Function const *F) const;
175
  std::string getNodeStyle(llvm::Value const *v) const;
176
  std::string getNodeStyle(MSSAVar const *v) const;
177
  static std::string getNodeStyle(llvm::Function const *f);
178
  static std::string getCallNodeStyle(llvm::Value const *v);
179
180
  struct DGDebugLoc {
181
    llvm::Function const *F;
182
    std::string filename;
183
    int line;
184
185
6
    bool operator<(DGDebugLoc const &o) const { return line < o.line; }
186
  };
187
188
  static bool getDGDebugLoc(llvm::Value const *v, DGDebugLoc &DL);
189
  static bool getDGDebugLoc(MSSAVar *v, DGDebugLoc &DL);
190
  static std::string getStringMsg(llvm::Value const *v);
191
  static std::string getStringMsg(MSSAVar *v);
192
  static bool getDebugTrace(std::vector<DGDebugLoc> &DLs, std::string &trace,
193
                            llvm::Instruction const *collective);
194
  static void reorderAndRemoveDup(std::vector<DGDebugLoc> &DLs);
195
196
  /* options */
197
  bool noPtrDep;
198
  bool noPred;
199
  bool disablePhiElim;
200
};
201
202
class DepGraphDCFAnalysis
203
    : public llvm::AnalysisInfoMixin<DepGraphDCFAnalysis> {
204
  friend llvm::AnalysisInfoMixin<DepGraphDCFAnalysis>;
205
  static llvm::AnalysisKey Key;
206
  bool ContextInsensitive_;
207
208
public:
209
  DepGraphDCFAnalysis(bool ContextInsensitive)
210
1.82k
      : ContextInsensitive_(ContextInsensitive){};
211
  // We return a unique_ptr to ensure stability of the analysis' internal state.
212
  using Result = std::unique_ptr<DepGraphDCF>;
213
  Result run(llvm::Module &M, llvm::ModuleAnalysisManager &);
214
};
215
} // namespace parcoach