/builds/2mk6rsew/0/parcoach/parcoach/src/aSSA/DepGraphDCF.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "parcoach/DepGraphDCF.h" |
2 | | |
3 | | #include "MSSAMuChi.h" |
4 | | #include "PTACallGraph.h" |
5 | | #include "Utils.h" |
6 | | #include "parcoach/Options.h" |
7 | | |
8 | | #include "llvm/Analysis/PostDominators.h" |
9 | | #include "llvm/IR/DebugInfo.h" |
10 | | #include "llvm/IR/DebugInfoMetadata.h" |
11 | | #include "llvm/Support/FileSystem.h" |
12 | | #include "llvm/Support/raw_ostream.h" |
13 | | |
14 | | #include <algorithm> |
15 | | #include <fstream> |
16 | | #include <queue> |
17 | | |
18 | | #define DEBUG_TYPE "dgdcf" |
19 | | |
20 | | using namespace llvm; |
21 | | namespace parcoach { |
22 | | namespace { |
23 | | struct FunctionArg { |
24 | | std::string Name; |
25 | | int Arg; |
26 | | }; |
27 | | |
28 | | std::vector<FunctionArg> SsaSourceFunctions; |
29 | | std::vector<FunctionArg> ValueSourceFunctions; |
30 | | std::vector<char const *> LoadValueSources; |
31 | | std::vector<FunctionArg> ResetFunctions; |
32 | | cl::opt<bool> OptWeakUpdate("weak-update", cl::desc("Weak update"), |
33 | | cl::cat(ParcoachCategory)); |
34 | | } // namespace |
35 | | |
36 | | DepGraphDCF::DepGraphDCF(MemorySSA *Mssa, PTACallGraph const &CG, |
37 | | FunctionAnalysisManager &AM, Module &M, |
38 | | bool ContextInsensitive, bool NoPtrDep, bool NoPred, |
39 | | bool DisablePhiElim) |
40 | | : mssa(Mssa), CG(CG), FAM(AM), M(M), ContextInsensitive(ContextInsensitive), |
41 | | PDT(nullptr), noPtrDep(NoPtrDep), noPred(NoPred), |
42 | 1.76k | disablePhiElim(DisablePhiElim) { |
43 | | |
44 | 1.76k | if (Options::get().isActivated(Paradigm::MPI)) { |
45 | 1.74k | enableMPI(); |
46 | 1.74k | } |
47 | 1.76k | #ifdef PARCOACH_ENABLE_OPENMP |
48 | 1.76k | if (Options::get().isActivated(Paradigm::OMP)) { |
49 | 15 | enableOMP(); |
50 | 15 | } |
51 | 1.76k | #endif |
52 | | #ifdef PARCOACH_ENABLE_UPC |
53 | | if (Options::get().isActivated(Paradigm::UPC)) |
54 | | enableUPC(); |
55 | | #endif |
56 | | #ifdef PARCOACH_ENABLE_CUDA |
57 | | if (Options::get().isActivated(Paradigm::CUDA)) |
58 | | enableCUDA(); |
59 | | #endif |
60 | 1.76k | build(); |
61 | 1.76k | } |
62 | | |
63 | 1.76k | DepGraphDCF::~DepGraphDCF() {} |
64 | | |
65 | 1.76k | void DepGraphDCF::build() { |
66 | 1.76k | TimeTraceScope TTS("DepGraphDCF"); |
67 | 19.8k | for (Function const &F : M) { |
68 | 19.8k | if (!CG.isReachableFromEntry(F)) { |
69 | 1.91k | continue; |
70 | 1.91k | } |
71 | | |
72 | 17.9k | if (isIntrinsicDbgFunction(&F)) { |
73 | 0 | continue; |
74 | 0 | } |
75 | | |
76 | 17.9k | buildFunction(&F); |
77 | 17.9k | } |
78 | | |
79 | 1.76k | if (!disablePhiElim) { |
80 | 1.76k | phiElimination(); |
81 | 1.76k | } |
82 | | |
83 | | // Compute tainted values |
84 | 1.76k | if (ContextInsensitive) { |
85 | 1 | computeTaintedValuesContextInsensitive(); |
86 | 1.75k | } else { |
87 | 1.75k | computeTaintedValuesContextSensitive(); |
88 | 1.75k | } |
89 | | |
90 | 1.76k | LLVM_DEBUG({ |
91 | 1.76k | dbgs() << "Tainted values (" << taintedLLVMNodes.size() << "/" |
92 | 1.76k | << taintedSSANodes.size() << "):\n"; |
93 | 1.76k | for (auto *V : taintedLLVMNodes) { |
94 | 1.76k | V->print(dbgs()); |
95 | 1.76k | dbgs() << "\n"; |
96 | 1.76k | } |
97 | 1.76k | }); |
98 | 1.76k | } |
99 | | |
100 | 1.74k | void DepGraphDCF::enableMPI() { |
101 | 1.74k | ResetFunctions.push_back({"MPI_Bcast", 0}); |
102 | 1.74k | ResetFunctions.push_back({"MPI_Allgather", 3}); |
103 | 1.74k | ResetFunctions.push_back({"MPI_Allgatherv", 3}); |
104 | 1.74k | ResetFunctions.push_back({"MPI_Alltoall", 3}); |
105 | 1.74k | ResetFunctions.push_back({"MPI_Alltoallv", 4}); |
106 | 1.74k | ResetFunctions.push_back({"MPI_Alltoallw", 4}); |
107 | 1.74k | ResetFunctions.push_back({"MPI_Allreduce", 1}); |
108 | 1.74k | SsaSourceFunctions.push_back({"MPI_Comm_rank", 1}); |
109 | 1.74k | SsaSourceFunctions.push_back({"MPI_Group_rank", 1}); |
110 | 1.74k | } |
111 | | |
112 | 15 | void DepGraphDCF::enableOMP() { |
113 | 15 | ValueSourceFunctions.push_back({"__kmpc_global_thread_num", -1}); |
114 | 15 | ValueSourceFunctions.push_back({"_omp_get_thread_num", -1}); |
115 | 15 | ValueSourceFunctions.push_back({"omp_get_thread_num", -1}); |
116 | 15 | } |
117 | | |
118 | 0 | void DepGraphDCF::enableUPC() { LoadValueSources.push_back("gasneti_mynode"); } |
119 | | |
120 | 0 | void DepGraphDCF::enableCUDA() { |
121 | | // threadIdx.x |
122 | 0 | ValueSourceFunctions.push_back({"llvm.nvvm.read.ptx.sreg.tid.x", -1}); |
123 | | // threadIdx.y |
124 | 0 | ValueSourceFunctions.push_back({"llvm.nvvm.read.ptx.sreg.tid.y", -1}); |
125 | | // threadIdx.z |
126 | 0 | ValueSourceFunctions.push_back({"llvm.nvvm.read.ptx.sreg.tid.z", -1}); |
127 | 0 | } |
128 | | |
129 | 17.9k | void DepGraphDCF::buildFunction(llvm::Function const *F) { |
130 | 17.9k | TimeTraceScope TTS("BuildGraph"); |
131 | | |
132 | 17.9k | curFunc = F; |
133 | | |
134 | 17.9k | if (F->isDeclaration()) { |
135 | 16.1k | PDT = nullptr; |
136 | 16.1k | } else { |
137 | 1.82k | PDT = &FAM.getResult<PostDominatorTreeAnalysis>(*const_cast<Function *>(F)); |
138 | 1.82k | } |
139 | | |
140 | 17.9k | visit(*const_cast<Function *>(F)); |
141 | | |
142 | | // Add entry chi nodes to the graph. |
143 | 40.3k | for (auto const &Chi : getRange(mssa->getFunToEntryChiMap(), F)) { |
144 | 40.3k | assert(Chi && Chi->var); |
145 | 40.3k | funcToSSANodesMap[F].insert(Chi->var.get()); |
146 | 40.3k | if (Chi->opVar) { |
147 | 0 | funcToSSANodesMap[F].insert(Chi->opVar); |
148 | 0 | addEdge(Chi->opVar, Chi->var.get()); |
149 | 0 | } |
150 | 40.3k | } |
151 | | |
152 | | // External functions |
153 | 17.9k | if (F->isDeclaration()) { |
154 | | |
155 | | // Add var arg entry and exit chi nodes. |
156 | 16.1k | if (F->isVarArg()) { |
157 | 5.13k | for (auto const &I : getRange(mssa->getExtCSToVArgEntryChi(), F)) { |
158 | 5.13k | MSSAChi *EntryChi = I.second.get(); |
159 | 5.13k | assert(EntryChi && EntryChi->var && "cs to vararg not found"); |
160 | 5.13k | funcToSSANodesMap[F].emplace(EntryChi->var.get()); |
161 | 5.13k | } |
162 | 5.13k | for (auto const &I : getRange(mssa->getExtCSToVArgExitChi(), F)) { |
163 | 5.13k | MSSAChi *ExitChi = I.second.get(); |
164 | 5.13k | assert(ExitChi && ExitChi->var); |
165 | 5.13k | funcToSSANodesMap[F].insert(ExitChi->var.get()); |
166 | 5.13k | addEdge(ExitChi->opVar, ExitChi->var.get()); |
167 | 5.13k | } |
168 | 1.71k | } |
169 | | |
170 | | // Add args entry and exit chi nodes for external functions. |
171 | 16.1k | unsigned ArgNo = 0; |
172 | 40.2k | for (Argument const &Arg : F->args()) { |
173 | 40.2k | if (!Arg.getType()->isPointerTy()) { |
174 | 6.92k | ArgNo++; |
175 | 6.92k | continue; |
176 | 6.92k | } |
177 | | |
178 | 54.9k | for (auto const &I : getRange(mssa->getExtCSToArgEntryChi(), F)) { |
179 | 54.9k | MSSAChi *EntryChi = I.second.at(ArgNo); |
180 | 54.9k | assert(EntryChi && EntryChi->var && "cs to arg not found"); |
181 | 54.9k | funcToSSANodesMap[F].emplace(EntryChi->var.get()); |
182 | 54.9k | } |
183 | 54.9k | for (auto const &I : getRange(mssa->getExtCSToArgExitChi(), F)) { |
184 | 54.9k | MSSAChi *ExitChi = I.second.at(ArgNo); |
185 | 54.9k | assert(ExitChi && ExitChi->var); |
186 | 54.9k | funcToSSANodesMap[F].emplace(ExitChi->var.get()); |
187 | 54.9k | addEdge(ExitChi->opVar, ExitChi->var.get()); |
188 | 54.9k | } |
189 | | |
190 | 33.3k | ArgNo++; |
191 | 33.3k | } |
192 | | |
193 | | // Add retval chi node for external functions |
194 | 16.1k | if (F->getReturnType()->isPointerTy()) { |
195 | 2.55k | for (auto const &I : getRange(mssa->getExtCSToCalleeRetChi(), F)) { |
196 | 2.55k | MSSAChi *RetChi = I.second.get(); |
197 | 2.55k | assert(RetChi && RetChi->var); |
198 | 2.55k | funcToSSANodesMap[F].emplace(RetChi->var.get()); |
199 | 2.55k | } |
200 | 752 | } |
201 | | |
202 | | // memcpy |
203 | 16.1k | if (F->getName().find("memcpy") != StringRef::npos) { |
204 | 2 | auto CSToArgEntry = mssa->getExtCSToArgEntryChi().lookup(F); |
205 | 2 | auto CSToArgExit = mssa->getExtCSToArgExitChi().lookup(F); |
206 | 3 | for (auto I : CSToArgEntry) { |
207 | 3 | CallBase *CS = I.first; |
208 | 3 | MSSAChi *SrcEntryChi = CSToArgEntry[CS][1]; |
209 | 3 | MSSAChi *DstExitChi = CSToArgExit[CS][0]; |
210 | | |
211 | 3 | addEdge(SrcEntryChi->var.get(), DstExitChi->var.get()); |
212 | | |
213 | | // llvm.mempcy instrinsic returns void whereas memcpy returns dst |
214 | 3 | if (F->getReturnType()->isPointerTy()) { |
215 | 3 | MSSAChi *RetChi{}; |
216 | 3 | auto It = mssa->getExtCSToCalleeRetChi().find(F); |
217 | 3 | if (It != mssa->getExtCSToCalleeRetChi().end()) { |
218 | 3 | RetChi = It->second.at(CS).get(); |
219 | 3 | } |
220 | 3 | addEdge(DstExitChi->var.get(), RetChi->var.get()); |
221 | 3 | } |
222 | 3 | } |
223 | 2 | } |
224 | | |
225 | | // memmove |
226 | 16.1k | else if (F->getName().find("memmove") != StringRef::npos) { |
227 | 1 | auto CSToArgEntry = mssa->getExtCSToArgEntryChi().lookup(F); |
228 | 1 | auto CSToArgExit = mssa->getExtCSToArgExitChi().lookup(F); |
229 | 1 | for (auto I : CSToArgEntry) { |
230 | 1 | CallBase *CS = I.first; |
231 | | |
232 | 1 | MSSAChi *SrcEntryChi = CSToArgEntry[CS][1]; |
233 | 1 | MSSAChi *DstExitChi = CSToArgExit[CS][0]; |
234 | | |
235 | 1 | addEdge(SrcEntryChi->var.get(), DstExitChi->var.get()); |
236 | | |
237 | | // llvm.memmove instrinsic returns void whereas memmove returns dst |
238 | 1 | if (F->getReturnType()->isPointerTy()) { |
239 | 1 | MSSAChi *RetChi{}; |
240 | 1 | auto It = mssa->getExtCSToCalleeRetChi().find(F); |
241 | 1 | if (It != mssa->getExtCSToCalleeRetChi().end()) { |
242 | 1 | RetChi = It->second.at(CS).get(); |
243 | 1 | } |
244 | 1 | addEdge(DstExitChi->var.get(), RetChi->var.get()); |
245 | 1 | } |
246 | 1 | } |
247 | 1 | } |
248 | | |
249 | | // memset |
250 | 16.1k | else if (F->getName().find("memset") != StringRef::npos) { |
251 | 1 | for (auto const &I : getRange(mssa->getExtCSToArgExitChi(), F)) { |
252 | 1 | CallBase *CS = I.first; |
253 | | |
254 | 1 | MSSAChi *ArgExitChi = mssa->getExtCSToArgExitChi().lookup(F)[CS][0]; |
255 | 1 | addEdge(F->getArg(1), ArgExitChi->var.get()); |
256 | | |
257 | | // llvm.memset instrinsic returns void whereas memset returns dst |
258 | 1 | if (F->getReturnType()->isPointerTy()) { |
259 | 1 | MSSAChi *RetChi{}; |
260 | 1 | auto It = mssa->getExtCSToCalleeRetChi().find(F); |
261 | 1 | if (It != mssa->getExtCSToCalleeRetChi().end()) { |
262 | 1 | RetChi = It->second.at(CS).get(); |
263 | 1 | } |
264 | 1 | addEdge(ArgExitChi->var.get(), RetChi->var.get()); |
265 | 1 | } |
266 | 1 | } |
267 | 1 | } |
268 | | |
269 | | // Unknown external function, we have to connect every input to every |
270 | | // output. |
271 | 16.1k | else { |
272 | 27.3k | for (CallBase *Cs : getRange(mssa->getExtFuncToCSMap(), F)) { |
273 | 27.3k | std::set<MSSAVar *> SsaOutputs; |
274 | 27.3k | std::set<MSSAVar *> SsaInputs; |
275 | | |
276 | | // Compute SSA outputs |
277 | 27.3k | auto const &CSToArgExit = mssa->getExtCSToArgExitChi(); |
278 | 27.3k | auto const &CSToArgEntry = mssa->getExtCSToArgEntryChi(); |
279 | 27.3k | auto IndexToExitChi = CSToArgExit.lookup(F)[Cs]; |
280 | 54.9k | for (auto &I : IndexToExitChi) { |
281 | 54.9k | MSSAChi *ArgExitChi = I.second; |
282 | 54.9k | SsaOutputs.emplace(ArgExitChi->var.get()); |
283 | 54.9k | } |
284 | 27.3k | if (F->isVarArg()) { |
285 | 5.13k | MSSAChi *VarArgExitChi{}; |
286 | 5.13k | auto It = mssa->getExtCSToVArgExitChi().find(F); |
287 | 5.13k | if (It != mssa->getExtCSToVArgExitChi().end()) { |
288 | 5.13k | VarArgExitChi = It->second.at(Cs).get(); |
289 | 5.13k | } |
290 | 5.13k | SsaOutputs.emplace(VarArgExitChi->var.get()); |
291 | 5.13k | } |
292 | 27.3k | if (F->getReturnType()->isPointerTy()) { |
293 | 2.54k | MSSAChi *RetChi{}; |
294 | 2.54k | auto It = mssa->getExtCSToCalleeRetChi().find(F); |
295 | 2.54k | if (It != mssa->getExtCSToCalleeRetChi().end()) { |
296 | 2.54k | RetChi = It->second.at(Cs).get(); |
297 | 2.54k | } |
298 | 2.54k | SsaOutputs.emplace(RetChi->var.get()); |
299 | 2.54k | } |
300 | | |
301 | | // Compute SSA inputs |
302 | 27.3k | auto IndexToEntryChi = CSToArgEntry.lookup(F)[Cs]; |
303 | 54.9k | for (auto &I : IndexToEntryChi) { |
304 | 54.9k | MSSAChi *ArgEntryChi = I.second; |
305 | 54.9k | SsaInputs.emplace(ArgEntryChi->var.get()); |
306 | 54.9k | } |
307 | 27.3k | if (F->isVarArg()) { |
308 | 5.13k | MSSAChi *VarArgEntryChi{}; |
309 | 5.13k | auto It = mssa->getExtCSToVArgEntryChi().find(F); |
310 | 5.13k | if (It != mssa->getExtCSToVArgEntryChi().end()) { |
311 | 5.13k | VarArgEntryChi = It->second.at(Cs).get(); |
312 | 5.13k | } |
313 | 5.13k | SsaInputs.emplace(VarArgEntryChi->var.get()); |
314 | 5.13k | } |
315 | | |
316 | | // Connect SSA inputs to SSA outputs |
317 | 60.0k | for (MSSAVar *In : SsaInputs) { |
318 | 231k | for (MSSAVar *Out : SsaOutputs) { |
319 | 231k | addEdge(In, Out); |
320 | 231k | } |
321 | 60.0k | } |
322 | | |
323 | | // Connect LLVM arguments to SSA outputs |
324 | 67.3k | for (Argument const &Arg : F->args()) { |
325 | 272k | for (MSSAVar *Out : SsaOutputs) { |
326 | 272k | addEdge(&Arg, Out); |
327 | 272k | } |
328 | 67.3k | } |
329 | 27.3k | } |
330 | 16.1k | } |
331 | | |
332 | | // SSA Source functions |
333 | 32.1k | for (auto const &[Name, ArgNo] : SsaSourceFunctions) { |
334 | 32.1k | if (F->getName() != Name) { |
335 | 30.3k | continue; |
336 | 30.3k | } |
337 | 1.74k | for (auto const &I : getRange(mssa->getExtCSToArgExitChi(), F)) { |
338 | 1.74k | assert(I.second.at(ArgNo)); |
339 | 1.74k | ssaSources.emplace(I.second.at(ArgNo)->var.get()); |
340 | 1.74k | } |
341 | 1.73k | } |
342 | 16.1k | } |
343 | 17.9k | } |
344 | | |
345 | 15.0k | void DepGraphDCF::visitBasicBlock(llvm::BasicBlock &BB) { |
346 | | // Add MSSA Phi nodes and edges to the graph. |
347 | 15.0k | for (auto const &Phi : getRange(mssa->getBBToPhiMap(), &BB)) { |
348 | 8.11k | assert(Phi && Phi->var); |
349 | 8.11k | funcToSSANodesMap[curFunc].insert(Phi->var.get()); |
350 | 16.3k | for (auto I : Phi->opsVar) { |
351 | 16.3k | assert(I.second); |
352 | 16.3k | funcToSSANodesMap[curFunc].insert(I.second); |
353 | 16.3k | addEdge(I.second, Phi->var.get()); |
354 | 16.3k | } |
355 | | |
356 | 8.11k | if (!noPred) { |
357 | 8.98k | for (Value const *Pred : Phi->preds) { |
358 | 8.98k | funcToLLVMNodesMap[curFunc].insert(Pred); |
359 | 8.98k | addEdge(Pred, Phi->var.get()); |
360 | 8.98k | } |
361 | 8.11k | } |
362 | 8.11k | } |
363 | 15.0k | } |
364 | | |
365 | 28.0k | void DepGraphDCF::visitAllocaInst(llvm::AllocaInst &I) { |
366 | | // Do nothing |
367 | 28.0k | } |
368 | | |
369 | 15.0k | void DepGraphDCF::visitTerminator(llvm::Instruction &I) { |
370 | | // Do nothing |
371 | 15.0k | } |
372 | | |
373 | 5.47k | void DepGraphDCF::visitCmpInst(llvm::CmpInst &I) { |
374 | | // Cmp instruction is a value, connect the result to its operands. |
375 | 5.47k | funcToLLVMNodesMap[curFunc].insert(&I); |
376 | | |
377 | 10.9k | for (Value const *V : I.operands()) { |
378 | 10.9k | addEdge(V, &I); |
379 | 10.9k | funcToLLVMNodesMap[curFunc].insert(V); |
380 | 10.9k | } |
381 | 5.47k | } |
382 | | |
383 | 1 | void DepGraphDCF::visitUnaryOperator(llvm::UnaryOperator &I) { |
384 | 1 | funcToLLVMNodesMap[curFunc].insert(&I); |
385 | | |
386 | 1 | for (Value const *V : I.operands()) { |
387 | 1 | addEdge(V, &I); |
388 | 1 | funcToLLVMNodesMap[curFunc].insert(V); |
389 | 1 | } |
390 | 1 | } |
391 | | |
392 | 1 | void DepGraphDCF::visitFreezeInst(llvm::FreezeInst &I) { |
393 | 1 | funcToLLVMNodesMap[curFunc].insert(&I); |
394 | | |
395 | 1 | for (Value const *V : I.operands()) { |
396 | 1 | addEdge(V, &I); |
397 | 1 | funcToLLVMNodesMap[curFunc].insert(V); |
398 | 1 | } |
399 | 1 | } |
400 | | |
401 | 43.9k | void DepGraphDCF::visitLoadInst(llvm::LoadInst &LI) { |
402 | | // Load inst, connect MSSA mus and the pointer loaded. |
403 | 43.9k | funcToLLVMNodesMap[curFunc].insert(&LI); |
404 | 43.9k | funcToLLVMNodesMap[curFunc].insert(LI.getPointerOperand()); |
405 | | |
406 | 43.9k | auto const &MuSetForLoad = getRange(mssa->getLoadToMuMap(), &LI); |
407 | 43.9k | for (auto const &Mu : MuSetForLoad) { |
408 | 43.9k | assert(Mu && Mu->var); |
409 | 43.9k | funcToSSANodesMap[curFunc].emplace(Mu->var); |
410 | 43.9k | addEdge(Mu->var, &LI); |
411 | 43.9k | } |
412 | | |
413 | | // Load value rank source |
414 | 43.9k | for (auto const &Name : LoadValueSources) { |
415 | 0 | if (LI.getPointerOperand()->getName() == Name) { |
416 | 0 | for (auto const &Mu : MuSetForLoad) { |
417 | 0 | assert(Mu && Mu->var); |
418 | 0 | ssaSources.emplace(Mu->var); |
419 | 0 | } |
420 | |
|
421 | 0 | break; |
422 | 0 | } |
423 | 0 | } |
424 | | |
425 | 43.9k | if (!noPtrDep) { |
426 | 43.9k | addEdge(LI.getPointerOperand(), &LI); |
427 | 43.9k | } |
428 | 43.9k | } |
429 | | |
430 | 26.4k | void DepGraphDCF::visitStoreInst(llvm::StoreInst &I) { |
431 | | // Store inst |
432 | | // For each chi, connect the pointer, the value stored and the MSSA operand. |
433 | 26.4k | for (auto const &Chi : getRange(mssa->getStoreToChiMap(), &I)) { |
434 | 26.4k | assert(Chi && Chi->var && Chi->opVar); |
435 | 26.4k | funcToSSANodesMap[curFunc].emplace(Chi->var.get()); |
436 | 26.4k | funcToSSANodesMap[curFunc].emplace(Chi->opVar); |
437 | 26.4k | funcToLLVMNodesMap[curFunc].emplace(I.getPointerOperand()); |
438 | 26.4k | funcToLLVMNodesMap[curFunc].emplace(I.getValueOperand()); |
439 | | |
440 | 26.4k | addEdge(I.getValueOperand(), Chi->var.get()); |
441 | | |
442 | 26.4k | if (OptWeakUpdate) { |
443 | 0 | addEdge(Chi->opVar, Chi->var.get()); |
444 | 0 | } |
445 | | |
446 | 26.4k | if (!noPtrDep) { |
447 | 26.4k | addEdge(I.getPointerOperand(), Chi->var.get()); |
448 | 26.4k | } |
449 | 26.4k | } |
450 | 26.4k | } |
451 | | |
452 | 2.77k | void DepGraphDCF::visitGetElementPtrInst(llvm::GetElementPtrInst &I) { |
453 | | // GetElementPtr, connect operands. |
454 | 2.77k | funcToLLVMNodesMap[curFunc].insert(&I); |
455 | | |
456 | 6.99k | for (Value const *V : I.operands()) { |
457 | 6.99k | addEdge(V, &I); |
458 | 6.99k | funcToLLVMNodesMap[curFunc].insert(V); |
459 | 6.99k | } |
460 | 2.77k | } |
461 | 49 | void DepGraphDCF::visitPHINode(llvm::PHINode &I) { |
462 | | // Connect LLVM Phi, connect operands and predicates. |
463 | 49 | funcToLLVMNodesMap[curFunc].insert(&I); |
464 | | |
465 | 98 | for (Value const *V : I.operands()) { |
466 | 98 | addEdge(V, &I); |
467 | 98 | funcToLLVMNodesMap[curFunc].insert(V); |
468 | 98 | } |
469 | | |
470 | 49 | if (!noPred) { |
471 | 50 | for (Value const *V : getRange(mssa->getPhiToPredMap(), &I)) { |
472 | 50 | addEdge(V, &I); |
473 | 50 | funcToLLVMNodesMap[curFunc].insert(V); |
474 | 50 | } |
475 | 49 | } |
476 | 49 | } |
477 | 6.85k | void DepGraphDCF::visitCastInst(llvm::CastInst &I) { |
478 | | // Cast inst, connect operands |
479 | 6.85k | funcToLLVMNodesMap[curFunc].insert(&I); |
480 | | |
481 | 6.85k | for (Value const *V : I.operands()) { |
482 | 6.85k | addEdge(V, &I); |
483 | 6.85k | funcToLLVMNodesMap[curFunc].insert(V); |
484 | 6.85k | } |
485 | 6.85k | } |
486 | 5 | void DepGraphDCF::visitSelectInst(llvm::SelectInst &I) { |
487 | | // Select inst, connect operands |
488 | 5 | funcToLLVMNodesMap[curFunc].insert(&I); |
489 | | |
490 | 15 | for (Value const *V : I.operands()) { |
491 | 15 | addEdge(V, &I); |
492 | 15 | funcToLLVMNodesMap[curFunc].insert(V); |
493 | 15 | } |
494 | 5 | } |
495 | 5.71k | void DepGraphDCF::visitBinaryOperator(llvm::BinaryOperator &I) { |
496 | | // Binary op, connect operands |
497 | 5.71k | funcToLLVMNodesMap[curFunc].insert(&I); |
498 | | |
499 | 11.4k | for (Value const *V : I.operands()) { |
500 | 11.4k | addEdge(V, &I); |
501 | 11.4k | funcToLLVMNodesMap[curFunc].insert(V); |
502 | 11.4k | } |
503 | 5.71k | } |
504 | | |
505 | 53.8k | void DepGraphDCF::visitCallInst(llvm::CallInst &CI) { |
506 | | /* Building rules for call sites : |
507 | | * |
508 | | * %c = call f (..., %a, ...) |
509 | | * [ mu(..., o1, ...) ] |
510 | | * [ ... |
511 | | * o2 = chi(o1) |
512 | | * ... ] |
513 | | * |
514 | | * define f (..., %b, ...) { |
515 | | * [ ..., o0 = X(o), ... ] |
516 | | * |
517 | | * ... |
518 | | * |
519 | | * [ ... |
520 | | * mu(on) |
521 | | * ... ] |
522 | | * ret %r |
523 | | * } |
524 | | * |
525 | | * Top-level variables |
526 | | * |
527 | | * rule1: %a -----> %b |
528 | | * rule2: %c <----- %r |
529 | | * |
530 | | * Address-taken variables |
531 | | * |
532 | | * rule3: o1 ------> o0 in f |
533 | | * rule4: o1 ------> o2 |
534 | | * rule5: o2 <------ on in f |
535 | | */ |
536 | | |
537 | 53.8k | if (isIntrinsicDbgInst(&CI)) { |
538 | 26.2k | return; |
539 | 26.2k | } |
540 | | |
541 | 27.5k | connectCSMus(CI); |
542 | 27.5k | connectCSChis(CI); |
543 | 27.5k | connectCSEffectiveParameters(CI); |
544 | 27.5k | connectCSCalledReturnValue(CI); |
545 | 27.5k | connectCSRetChi(CI); |
546 | | |
547 | | // Add call node |
548 | 27.5k | funcToCallNodes[curFunc].insert(&CI); |
549 | | |
550 | | // Add pred to call edges |
551 | 27.5k | std::set<Value const *> Preds = computeIPDFPredicates(*PDT, CI.getParent()); |
552 | 27.5k | for (Value const *Pred : Preds) { |
553 | 11.7k | condToCallEdges[Pred].insert(&CI); |
554 | 11.7k | callsiteToConds[&CI].insert(Pred); |
555 | 11.7k | } |
556 | | |
557 | | // Add call to func edge |
558 | 27.5k | Function const *Callee = CI.getCalledFunction(); |
559 | | |
560 | | // direct call |
561 | 27.5k | if (Callee) { |
562 | 27.5k | callToFuncEdges[&CI] = Callee; |
563 | 27.5k | funcToCallSites[Callee].insert(&CI); |
564 | | |
565 | | // Return value source |
566 | 27.5k | for (auto const &[Name, ArgNo] : ValueSourceFunctions) { |
567 | 501 | if (Callee->getName() != Name) { |
568 | 452 | continue; |
569 | 452 | } |
570 | | |
571 | 49 | if (ArgNo != -1) { |
572 | 0 | continue; |
573 | 0 | } |
574 | | |
575 | 49 | valueSources.insert(&CI); |
576 | 49 | } |
577 | 27.5k | } |
578 | | |
579 | | // indirect call |
580 | 3 | else { |
581 | 6 | for (Function const *MayCallee : getRange(CG.getIndirectCallMap(), &CI)) { |
582 | 6 | callToFuncEdges[&CI] = MayCallee; |
583 | 6 | funcToCallSites[MayCallee].insert(&CI); |
584 | | |
585 | | // Return value source |
586 | 6 | for (auto const &[Name, ArgNo] : ValueSourceFunctions) { |
587 | 6 | if (MayCallee->getName() != Name) { |
588 | 6 | continue; |
589 | 6 | } |
590 | | |
591 | 0 | if (ArgNo != -1) { |
592 | 0 | continue; |
593 | 0 | } |
594 | | |
595 | 0 | valueSources.insert(&CI); |
596 | 0 | } |
597 | 6 | } |
598 | 3 | } |
599 | | |
600 | | // Sync CHI |
601 | 27.5k | for (auto const &Chi : getRange(mssa->getCSToSynChiMap(), &CI)) { |
602 | 1 | assert(Chi && Chi->var && Chi->opVar); |
603 | 1 | funcToSSANodesMap[curFunc].emplace(Chi->var.get()); |
604 | 1 | funcToSSANodesMap[curFunc].emplace(Chi->opVar); |
605 | | |
606 | 1 | addEdge(Chi->opVar, Chi->var.get()); |
607 | 1 | taintResetSSANodes.emplace(Chi->var.get()); |
608 | 1 | } |
609 | 27.5k | } |
610 | | |
611 | 27.5k | void DepGraphDCF::connectCSMus(llvm::CallInst &I) { |
612 | | // Mu of the call site. |
613 | 54.9k | for (auto const &Mu : getRange(mssa->getCSToMuMap(), &I)) { |
614 | 54.9k | assert(Mu && Mu->var); |
615 | 54.9k | funcToSSANodesMap[curFunc].emplace(Mu->var); |
616 | 54.9k | Function const *Called = NULL; |
617 | | |
618 | | // External Function, we connect call mu to artifical chi of the external |
619 | | // function for each argument. |
620 | 54.9k | if (MSSAExtCallMu *ExtCallMu = dyn_cast<MSSAExtCallMu>(Mu.get())) { |
621 | 54.7k | CallBase *CS(&I); |
622 | | |
623 | 54.7k | Called = ExtCallMu->called; |
624 | 54.7k | unsigned ArgNo = ExtCallMu->argNo; |
625 | | |
626 | | // Case where this is a var arg parameter |
627 | 54.7k | if (ArgNo >= Called->arg_size()) { |
628 | 6 | assert(Called->isVarArg()); |
629 | | |
630 | 6 | auto ItMap = mssa->getExtCSToVArgEntryChi().find(Called); |
631 | 6 | auto ItEnd = mssa->getExtCSToVArgEntryChi().end(); |
632 | 6 | MSSAChi *Chi{}; |
633 | 6 | if (ItMap != ItEnd) { |
634 | 6 | Chi = ItMap->second.at(CS).get(); |
635 | 6 | } |
636 | 6 | assert(Chi); |
637 | 6 | MSSAVar *Var = Chi->var.get(); |
638 | 6 | assert(Var); |
639 | 6 | funcToSSANodesMap[Called].emplace(Var); |
640 | 6 | addEdge(Mu->var, Var); // rule3 |
641 | 6 | } |
642 | | |
643 | 54.7k | else { |
644 | | // rule3 |
645 | 54.7k | auto const &CSToArgEntry = mssa->getExtCSToArgEntryChi(); |
646 | 54.7k | assert(CSToArgEntry.lookup(Called)[CS].at(ArgNo)); |
647 | 54.7k | addEdge(Mu->var, CSToArgEntry.lookup(Called)[CS].at(ArgNo)->var.get()); |
648 | 54.7k | } |
649 | | |
650 | 54.7k | continue; |
651 | 54.7k | } |
652 | | |
653 | 215 | MSSACallMu *CallMu = cast<MSSACallMu>(Mu.get()); |
654 | 215 | Called = CallMu->called; |
655 | | |
656 | 215 | auto const &FunctionToChi = mssa->getFunRegToEntryChiMap(); |
657 | | |
658 | 215 | auto It = FunctionToChi.find(Called); |
659 | 215 | if (It != FunctionToChi.end()) { |
660 | 215 | MSSAChi *EntryChi = It->second.at(Mu->region); |
661 | 215 | assert(EntryChi && EntryChi->var && "reg to entrychi not found"); |
662 | 215 | funcToSSANodesMap[Called].emplace(EntryChi->var.get()); |
663 | 215 | addEdge(CallMu->var, EntryChi->var.get()); // rule3 |
664 | 215 | } |
665 | 215 | } |
666 | 27.5k | } |
667 | | |
668 | 27.5k | void DepGraphDCF::connectCSChis(llvm::CallInst &I) { |
669 | | // Chi of the callsite. |
670 | 27.5k | for (auto const &Chi : getRange(mssa->getCSToChiMap(), &I)) { |
671 | 17.0k | assert(Chi && Chi->var && Chi->opVar); |
672 | 17.0k | funcToSSANodesMap[curFunc].emplace(Chi->opVar); |
673 | 17.0k | funcToSSANodesMap[curFunc].emplace(Chi->var.get()); |
674 | | |
675 | 17.0k | if (OptWeakUpdate) { |
676 | 0 | addEdge(Chi->opVar, Chi->var.get()); // rule4 |
677 | 0 | } |
678 | | |
679 | 17.0k | Function const *Called = NULL; |
680 | | |
681 | | // External Function, we connect call chi to artifical chi of the external |
682 | | // function for each argument. |
683 | 17.0k | if (MSSAExtCallChi *ExtCallChi = dyn_cast<MSSAExtCallChi>(Chi.get())) { |
684 | 16.9k | CallBase *CS(&I); |
685 | 16.9k | Called = ExtCallChi->called; |
686 | 16.9k | unsigned ArgNo = ExtCallChi->argNo; |
687 | | |
688 | | // Case where this is a var arg parameter. |
689 | 16.9k | if (ArgNo >= Called->arg_size()) { |
690 | 4 | assert(Called->isVarArg()); |
691 | | |
692 | 4 | auto ItMap = mssa->getExtCSToVArgExitChi().find(Called); |
693 | 4 | auto ItEnd = mssa->getExtCSToVArgExitChi().end(); |
694 | 4 | MSSAChi *Chi{}; |
695 | 4 | if (ItMap != ItEnd) { |
696 | 4 | Chi = ItMap->second.at(CS).get(); |
697 | 4 | } |
698 | 4 | assert(Chi); |
699 | 4 | MSSAVar *Var = Chi->var.get(); |
700 | 4 | assert(Var); |
701 | 4 | funcToSSANodesMap[Called].emplace(Var); |
702 | 4 | addEdge(Var, Chi->var.get()); // rule5 |
703 | 4 | } |
704 | | |
705 | 16.9k | else { |
706 | | // rule5 |
707 | 16.9k | auto const &CSToArgExit = mssa->getExtCSToArgExitChi(); |
708 | 16.9k | assert(CSToArgExit.lookup(Called)[CS].at(ArgNo)); |
709 | 16.9k | addEdge(CSToArgExit.lookup(Called)[CS].at(ArgNo)->var.get(), |
710 | 16.9k | Chi->var.get()); |
711 | | |
712 | | // Reset functions |
713 | 118k | for (auto const &[Name, FArgNo] : ResetFunctions) { |
714 | 118k | if (Called->getName() != Name) { |
715 | 117k | continue; |
716 | 117k | } |
717 | | |
718 | 1.44k | if ((int)ArgNo != FArgNo) { |
719 | 204 | continue; |
720 | 204 | } |
721 | | |
722 | 1.24k | taintResetSSANodes.emplace(Chi->var.get()); |
723 | 1.24k | } |
724 | 16.9k | } |
725 | | |
726 | 16.9k | continue; |
727 | 16.9k | } |
728 | | |
729 | 31 | MSSACallChi *CallChi = cast<MSSACallChi>(Chi.get()); |
730 | 31 | Called = CallChi->called; |
731 | | |
732 | 31 | auto const &FunctionToMu = mssa->getFunRegToReturnMuMap(); |
733 | 31 | auto It = FunctionToMu.find(Called); |
734 | 31 | if (It != FunctionToMu.end()) { |
735 | 31 | MSSAMu *ReturnMu = It->second.at(Chi->region); |
736 | 31 | assert(ReturnMu && ReturnMu->var && "entry not found in map"); |
737 | 31 | funcToSSANodesMap[Called].emplace(ReturnMu->var); |
738 | 31 | addEdge(ReturnMu->var, Chi->var.get()); // rule5 |
739 | 31 | } |
740 | 31 | } |
741 | 27.5k | } |
742 | | |
743 | 27.5k | void DepGraphDCF::connectCSEffectiveParameters(llvm::CallInst &I) { |
744 | | // Connect effective parameters to formal parameters. |
745 | 27.5k | Function const *Callee = I.getCalledFunction(); |
746 | | |
747 | | // direct call |
748 | 27.5k | if (Callee) { |
749 | 27.5k | if (Callee->isDeclaration()) { |
750 | 27.5k | connectCSEffectiveParametersExt(I, Callee); |
751 | 27.5k | return; |
752 | 27.5k | } |
753 | | |
754 | 60 | unsigned ArgIdx = 0; |
755 | 96 | for (Argument const &Arg : Callee->args()) { |
756 | 96 | funcToLLVMNodesMap[curFunc].insert(I.getArgOperand(ArgIdx)); |
757 | 96 | funcToLLVMNodesMap[Callee].insert(&Arg); |
758 | | |
759 | 96 | addEdge(I.getArgOperand(ArgIdx), &Arg); // rule1 |
760 | | |
761 | 96 | ArgIdx++; |
762 | 96 | } |
763 | 60 | } |
764 | | |
765 | | // indirect call |
766 | 3 | else { |
767 | 5 | for (Function const *MayCallee : getRange(CG.getIndirectCallMap(), &I)) { |
768 | 5 | if (MayCallee->isDeclaration()) { |
769 | 1 | connectCSEffectiveParametersExt(I, MayCallee); |
770 | 1 | return; |
771 | 1 | } |
772 | | |
773 | 4 | unsigned ArgIdx = 0; |
774 | 4 | for (Argument const &Arg : MayCallee->args()) { |
775 | 4 | funcToLLVMNodesMap[curFunc].insert(I.getArgOperand(ArgIdx)); |
776 | 4 | funcToLLVMNodesMap[Callee].insert(&Arg); |
777 | | |
778 | 4 | addEdge(I.getArgOperand(ArgIdx), &Arg); // rule1 |
779 | | |
780 | 4 | ArgIdx++; |
781 | 4 | } |
782 | 4 | } |
783 | 3 | } |
784 | 27.5k | } |
785 | | |
786 | | void DepGraphDCF::connectCSEffectiveParametersExt(CallInst &I, |
787 | 27.5k | Function const *Callee) { |
788 | 27.5k | CallBase *CS(&I); |
789 | | |
790 | 27.5k | if (Callee->getName().find("memset") != StringRef::npos) { |
791 | 2 | MSSAChi *ArgExitChi = mssa->getExtCSToArgExitChi().lookup(Callee)[CS][0]; |
792 | 2 | Value const *CArg = I.getArgOperand(1); |
793 | 2 | assert(CArg); |
794 | 2 | funcToLLVMNodesMap[I.getParent()->getParent()].emplace(CArg); |
795 | 2 | addEdge(CArg, ArgExitChi->var.get()); |
796 | 2 | } |
797 | 27.5k | } |
798 | | |
799 | 27.5k | void DepGraphDCF::connectCSCalledReturnValue(llvm::CallInst &I) { |
800 | | // If the function called returns a value, connect the return value to the |
801 | | // call value. |
802 | | |
803 | 27.5k | Function const *Callee = I.getCalledFunction(); |
804 | | |
805 | | // direct call |
806 | 27.5k | if (Callee) { |
807 | 27.5k | if (!Callee->isDeclaration() && !Callee->getReturnType()->isVoidTy()) { |
808 | 0 | funcToLLVMNodesMap[curFunc].insert(&I); |
809 | 0 | addEdge(getReturnValue(Callee), &I); // rule2 |
810 | 0 | } |
811 | 27.5k | } |
812 | | |
813 | | // indirect call |
814 | 3 | else { |
815 | 6 | for (Function const *MayCallee : getRange(CG.getIndirectCallMap(), &I)) { |
816 | 6 | if (!MayCallee->isDeclaration() && |
817 | 6 | !MayCallee->getReturnType()->isVoidTy()) { |
818 | 0 | funcToLLVMNodesMap[curFunc].insert(&I); |
819 | 0 | addEdge(getReturnValue(MayCallee), &I); // rule2 |
820 | 0 | } |
821 | 6 | } |
822 | 3 | } |
823 | 27.5k | } |
824 | | |
825 | 27.5k | void DepGraphDCF::connectCSRetChi(llvm::CallInst &I) { |
826 | | // External function, if the function called returns a pointer, connect the |
827 | | // artifical ret chi to the retcallchi |
828 | | // return chi of the caller. |
829 | | |
830 | 27.5k | Function const *Callee = I.getCalledFunction(); |
831 | 27.5k | CallBase *CS(&I); |
832 | | |
833 | | // direct call |
834 | 27.5k | if (Callee) { |
835 | 27.5k | if (Callee->isDeclaration() && Callee->getReturnType()->isPointerTy()) { |
836 | 2.60k | for (auto const &Chi : getRange(mssa->getExtCSToCallerRetChi(), &I)) { |
837 | 2.54k | assert(Chi && Chi->var && Chi->opVar); |
838 | 2.54k | funcToSSANodesMap[curFunc].emplace(Chi->var.get()); |
839 | 2.54k | funcToSSANodesMap[curFunc].emplace(Chi->opVar); |
840 | | |
841 | 2.54k | addEdge(Chi->opVar, Chi->var.get()); |
842 | 2.54k | auto ItMap = mssa->getExtCSToCalleeRetChi().find(Callee); |
843 | 2.54k | assert(ItMap != mssa->getExtCSToCalleeRetChi().end()); |
844 | 2.54k | addEdge(ItMap->second.at(CS)->var.get(), Chi->var.get()); |
845 | 2.54k | } |
846 | 2.60k | } |
847 | 27.5k | } |
848 | | |
849 | | // indirect call |
850 | 3 | else { |
851 | 6 | for (Function const *MayCallee : getRange(CG.getIndirectCallMap(), &I)) { |
852 | 6 | if (MayCallee->isDeclaration() && |
853 | 6 | MayCallee->getReturnType()->isPointerTy()) { |
854 | 1 | for (auto const &Chi : getRange(mssa->getExtCSToCallerRetChi(), &I)) { |
855 | 0 | assert(Chi && Chi->var && Chi->opVar); |
856 | 0 | funcToSSANodesMap[curFunc].emplace(Chi->var.get()); |
857 | 0 | funcToSSANodesMap[curFunc].emplace(Chi->opVar); |
858 | |
|
859 | 0 | addEdge(Chi->opVar, Chi->var.get()); |
860 | 0 | auto ItMap = mssa->getExtCSToCalleeRetChi().find(MayCallee); |
861 | 0 | assert(ItMap != mssa->getExtCSToCalleeRetChi().end()); |
862 | 0 | addEdge(ItMap->second.at(CS)->var.get(), Chi->var.get()); |
863 | 0 | } |
864 | 1 | } |
865 | 6 | } |
866 | 3 | } |
867 | 27.5k | } |
868 | | |
869 | 0 | void DepGraphDCF::visitExtractValueInst(llvm::ExtractValueInst &I) { |
870 | | // Connect operands |
871 | 0 | funcToLLVMNodesMap[curFunc].insert(&I); |
872 | |
|
873 | 0 | for (Value const *V : I.operands()) { |
874 | 0 | addEdge(V, &I); |
875 | 0 | funcToLLVMNodesMap[curFunc].insert(V); |
876 | 0 | } |
877 | 0 | } |
878 | | |
879 | 0 | void DepGraphDCF::visitExtractElementInst(llvm::ExtractElementInst &I) { |
880 | | // Connect operands |
881 | 0 | funcToLLVMNodesMap[curFunc].insert(&I); |
882 | |
|
883 | 0 | for (Value const *V : I.operands()) { |
884 | 0 | addEdge(V, &I); |
885 | 0 | funcToLLVMNodesMap[curFunc].insert(V); |
886 | 0 | } |
887 | 0 | } |
888 | | |
889 | 0 | void DepGraphDCF::visitInsertElementInst(llvm::InsertElementInst &I) { |
890 | | // Connect operands |
891 | 0 | funcToLLVMNodesMap[curFunc].insert(&I); |
892 | |
|
893 | 0 | for (Value const *V : I.operands()) { |
894 | 0 | addEdge(V, &I); |
895 | 0 | funcToLLVMNodesMap[curFunc].insert(V); |
896 | 0 | } |
897 | 0 | } |
898 | | |
899 | 0 | void DepGraphDCF::visitInsertValueInst(llvm::InsertValueInst &I) { |
900 | | // Connect operands |
901 | 0 | funcToLLVMNodesMap[curFunc].insert(&I); |
902 | |
|
903 | 0 | for (Value const *V : I.operands()) { |
904 | 0 | addEdge(V, &I); |
905 | 0 | funcToLLVMNodesMap[curFunc].insert(V); |
906 | 0 | } |
907 | 0 | } |
908 | | |
909 | 0 | void DepGraphDCF::visitShuffleVectorInst(llvm::ShuffleVectorInst &I) { |
910 | | // Connect operands |
911 | 0 | funcToLLVMNodesMap[curFunc].insert(&I); |
912 | |
|
913 | 0 | for (Value const *V : I.operands()) { |
914 | 0 | addEdge(V, &I); |
915 | 0 | funcToLLVMNodesMap[curFunc].insert(V); |
916 | 0 | } |
917 | 0 | } |
918 | | |
919 | 0 | void DepGraphDCF::visitInstruction(llvm::Instruction &I) { |
920 | 0 | errs() << "Error: Unhandled instruction " << I << "\n"; |
921 | 0 | } |
922 | | |
923 | 2 | void DepGraphDCF::toDot(StringRef Filename) const { |
924 | 2 | errs() << "Writing '" << Filename << "' ...\n"; |
925 | | |
926 | | // FIXME: restore timer with llvm ones |
927 | | |
928 | 2 | std::error_code EC; |
929 | 2 | raw_fd_ostream Stream(Filename, EC, sys::fs::OF_Text); |
930 | | |
931 | 2 | Stream << "digraph F {\n"; |
932 | 2 | Stream << "compound=true;\n"; |
933 | 2 | Stream << "rankdir=LR;\n"; |
934 | | |
935 | | // dot global LLVM values in a separate cluster |
936 | 2 | Stream << "\tsubgraph cluster_globalsvar {\n"; |
937 | 2 | Stream << "style=filled;\ncolor=lightgrey;\n"; |
938 | 2 | Stream << "label=< <B> Global Values </B> >;\n"; |
939 | 2 | Stream << "node [style=filled,color=white];\n"; |
940 | 16 | for (Value const &G : M.globals()) { |
941 | 16 | Stream << "Node" << ((void *)&G) << " [label=\"" << getValueLabel(&G) |
942 | 16 | << "\" " << getNodeStyle(&G) << "];\n"; |
943 | 16 | } |
944 | 2 | Stream << "}\n;"; |
945 | | |
946 | 18 | for (auto const &F : M) { |
947 | 18 | if (isIntrinsicDbgFunction(&F)) { |
948 | 2 | continue; |
949 | 2 | } |
950 | | |
951 | 16 | if (F.isDeclaration()) { |
952 | 10 | dotExtFunction(Stream, &F); |
953 | 10 | } else { |
954 | 6 | dotFunction(Stream, &F); |
955 | 6 | } |
956 | 16 | } |
957 | | |
958 | | // Edges |
959 | 32 | for (auto I : llvmToLLVMChildren) { |
960 | 32 | Value const *S = I.first; |
961 | 38 | for (Value const *D : I.second) { |
962 | 38 | Stream << "Node" << ((void *)S) << " -> " |
963 | 38 | << "Node" << ((void *)D) << "\n"; |
964 | 38 | } |
965 | 32 | } |
966 | | |
967 | 50 | for (auto I : llvmToSSAChildren) { |
968 | 50 | Value const *S = I.first; |
969 | 64 | for (MSSAVar *D : I.second) { |
970 | 64 | Stream << "Node" << ((void *)S) << " -> " |
971 | 64 | << "Node" << ((void *)D) << "\n"; |
972 | 64 | } |
973 | 50 | } |
974 | | |
975 | 48 | for (auto I : ssaToSSAChildren) { |
976 | 48 | MSSAVar *S = I.first; |
977 | 64 | for (MSSAVar *D : I.second) { |
978 | 64 | Stream << "Node" << ((void *)S) << " -> " |
979 | 64 | << "Node" << ((void *)D) << "\n"; |
980 | 64 | } |
981 | 48 | } |
982 | | |
983 | 12 | for (auto I : ssaToLLVMChildren) { |
984 | 12 | MSSAVar *S = I.first; |
985 | 16 | for (Value const *D : I.second) { |
986 | 16 | Stream << "Node" << ((void *)S) << " -> " |
987 | 16 | << "Node" << ((void *)D) << "\n"; |
988 | 16 | } |
989 | 12 | } |
990 | | |
991 | 26 | for (auto I : callToFuncEdges) { |
992 | 26 | Value const *Call = I.first; |
993 | 26 | Function const *F = I.second; |
994 | 26 | Stream << "NodeCall" << ((void *)Call) << " -> " |
995 | 26 | << "Node" << ((void *)F) << " [lhead=cluster_" << ((void *)F) |
996 | 26 | << "]\n"; |
997 | 26 | } |
998 | | |
999 | 2 | for (auto I : condToCallEdges) { |
1000 | 2 | Value const *S = I.first; |
1001 | 6 | for (Value const *Call : I.second) { |
1002 | 6 | Stream << "Node" << ((void *)S) << " -> " |
1003 | 6 | << "NodeCall" << ((void *)Call) << "\n"; |
1004 | 6 | } |
1005 | | /*if (taintedLLVMNodes.count(s) != 0){ |
1006 | | errs() << "DBG: " << s->getName() << " is a tainted condition \n"; |
1007 | | s->dump(); |
1008 | | }*/ |
1009 | 2 | } |
1010 | | |
1011 | 2 | Stream << "}\n"; |
1012 | 2 | } |
1013 | | |
1014 | 6 | void DepGraphDCF::dotFunction(raw_fd_ostream &Stream, Function const *F) const { |
1015 | 6 | Stream << "\tsubgraph cluster_" << ((void *)F) << " {\n"; |
1016 | 6 | Stream << "style=filled;\ncolor=lightgrey;\n"; |
1017 | 6 | Stream << "label=< <B>" << F->getName() << "</B> >;\n"; |
1018 | 6 | Stream << "node [style=filled,color=white];\n"; |
1019 | | |
1020 | | // Nodes with label |
1021 | 72 | for (Value const *V : getRange(funcToLLVMNodesMap, F)) { |
1022 | 72 | if (isa<GlobalValue>(V)) { |
1023 | 0 | continue; |
1024 | 0 | } |
1025 | 72 | Stream << "Node" << ((void *)V) << " [label=\"" << getValueLabel(V) << "\" " |
1026 | 72 | << getNodeStyle(V) << "];\n"; |
1027 | 72 | } |
1028 | | |
1029 | 78 | for (MSSAVar const *V : getRange(funcToSSANodesMap, F)) { |
1030 | 78 | Stream << "Node" << ((void *)V) << " [label=\"" << V->getName() |
1031 | 78 | << "\" shape=diamond " << getNodeStyle(V) << "];\n"; |
1032 | 78 | } |
1033 | | |
1034 | 26 | for (Value const *V : getRange(funcToCallNodes, F)) { |
1035 | 26 | Stream << "NodeCall" << ((void *)V) << " [label=\"" << getCallValueLabel(V) |
1036 | 26 | << "\" shape=rectangle " << getCallNodeStyle(V) << "];\n"; |
1037 | 26 | } |
1038 | | |
1039 | 6 | Stream << "Node" << ((void *)F) << " [style=invisible];\n"; |
1040 | | |
1041 | 6 | Stream << "}\n"; |
1042 | 6 | } |
1043 | | |
1044 | | void DepGraphDCF::dotExtFunction(raw_fd_ostream &Stream, |
1045 | 10 | Function const *F) const { |
1046 | 10 | Stream << "\tsubgraph cluster_" << ((void *)F) << " {\n"; |
1047 | 10 | Stream << "style=filled;\ncolor=lightgrey;\n"; |
1048 | 10 | Stream << "label=< <B>" << F->getName() << "</B> >;\n"; |
1049 | 10 | Stream << "node [style=filled,color=white];\n"; |
1050 | | |
1051 | | // Nodes with label |
1052 | 10 | for (Value const *V : getRange(funcToLLVMNodesMap, F)) { |
1053 | 0 | Stream << "Node" << ((void *)V) << " [label=\"" << getValueLabel(V) << "\" " |
1054 | 0 | << getNodeStyle(V) << "];\n"; |
1055 | 0 | } |
1056 | | |
1057 | 36 | for (MSSAVar const *V : getRange(funcToSSANodesMap, F)) { |
1058 | 36 | Stream << "Node" << ((void *)V) << " [label=\"" << V->getName() |
1059 | 36 | << "\" shape=diamond " << getNodeStyle(V) << "];\n"; |
1060 | 36 | } |
1061 | | |
1062 | 10 | Stream << "Node" << ((void *)F) << " [style=invisible];\n"; |
1063 | | |
1064 | 10 | Stream << "}\n"; |
1065 | 10 | } |
1066 | | |
1067 | 90 | std::string DepGraphDCF::getNodeStyle(llvm::Value const *V) const { |
1068 | 90 | if (taintedLLVMNodes.count(V) != 0) { |
1069 | 8 | return "style=filled, color=red"; |
1070 | 8 | } |
1071 | 82 | return "style=filled, color=white"; |
1072 | 90 | } |
1073 | | |
1074 | 115 | std::string DepGraphDCF::getNodeStyle(MSSAVar const *V) const { |
1075 | 115 | if (taintedSSANodes.count(V) != 0) { |
1076 | 6 | return "style=filled, color=red"; |
1077 | 6 | } |
1078 | 109 | return "style=filled, color=white"; |
1079 | 115 | } |
1080 | | |
1081 | 0 | std::string DepGraphDCF::getNodeStyle(Function const *F) { |
1082 | 0 | return "style=filled, color=white"; |
1083 | 0 | } |
1084 | | |
1085 | 26 | std::string DepGraphDCF::getCallNodeStyle(llvm::Value const *V) { |
1086 | 26 | return "style=filled, color=white"; |
1087 | 26 | } |
1088 | | |
1089 | 1 | void DepGraphDCF::computeTaintedValuesContextInsensitive() { |
1090 | | #ifndef NDEBUG |
1091 | | unsigned FuncToLlvmNodesMapSize = funcToLLVMNodesMap.size(); |
1092 | | unsigned FuncToSsaNodesMapSize = funcToSSANodesMap.size(); |
1093 | | unsigned VarArgNodeSize = varArgNodes.size(); |
1094 | | unsigned LlvmToLlvmChildrenSize = llvmToLLVMChildren.size(); |
1095 | | unsigned LlvmToLlvmParentsSize = llvmToLLVMParents.size(); |
1096 | | unsigned LlvmToSsaChildrenSize = llvmToSSAChildren.size(); |
1097 | | unsigned LlvmToSsaParentsSize = llvmToSSAParents.size(); |
1098 | | unsigned SsaToLlvmChildrenSize = ssaToLLVMChildren.size(); |
1099 | | unsigned SsaToLlvmParentsSize = ssaToLLVMParents.size(); |
1100 | | unsigned SsaToSsaChildrenSize = ssaToSSAChildren.size(); |
1101 | | unsigned SsaToSsaParentsSize = ssaToSSAParents.size(); |
1102 | | unsigned FuncToCallNodesSize = funcToCallNodes.size(); |
1103 | | unsigned CallToFuncEdgesSize = callToFuncEdges.size(); |
1104 | | unsigned CondToCallEdgesSize = condToCallEdges.size(); |
1105 | | unsigned FuncToCallSitesSize = funcToCallSites.size(); |
1106 | | unsigned CallsiteToCondsSize = callsiteToConds.size(); |
1107 | | #endif |
1108 | | |
1109 | 1 | TimeTraceScope TTS("FloodDep"); |
1110 | | |
1111 | 1 | std::queue<MSSAVar *> VarToVisit; |
1112 | 1 | std::queue<Value const *> ValueToVisit; |
1113 | | |
1114 | | // SSA sources |
1115 | 1 | for (MSSAVar const *Src : ssaSources) { |
1116 | 0 | taintedSSANodes.insert(Src); |
1117 | 0 | VarToVisit.push(const_cast<MSSAVar *>(Src)); |
1118 | 0 | } |
1119 | | |
1120 | | // Value sources |
1121 | 5 | for (Value const *Src : valueSources) { |
1122 | 5 | taintedLLVMNodes.insert(Src); |
1123 | 5 | ValueToVisit.push(Src); |
1124 | 5 | } |
1125 | | |
1126 | 10 | while (!VarToVisit.empty() || !ValueToVisit.empty()) { |
1127 | 9 | if (!VarToVisit.empty()) { |
1128 | 4 | MSSAVar *S = VarToVisit.front(); |
1129 | 4 | VarToVisit.pop(); |
1130 | | |
1131 | 4 | if (taintResetSSANodes.find(S) != taintResetSSANodes.end()) { |
1132 | 0 | continue; |
1133 | 0 | } |
1134 | | |
1135 | 4 | if (ssaToSSAChildren.find(S) != ssaToSSAChildren.end()) { |
1136 | 2 | for (MSSAVar *D : ssaToSSAChildren[S]) { |
1137 | 2 | if (taintedSSANodes.count(D) != 0) { |
1138 | 0 | continue; |
1139 | 0 | } |
1140 | | |
1141 | 2 | taintedSSANodes.insert(D); |
1142 | 2 | VarToVisit.push(D); |
1143 | 2 | } |
1144 | 2 | } |
1145 | | |
1146 | 4 | if (ssaToLLVMChildren.find(S) != ssaToLLVMChildren.end()) { |
1147 | 2 | for (Value const *D : ssaToLLVMChildren[S]) { |
1148 | 2 | if (taintedLLVMNodes.count(D) != 0) { |
1149 | 0 | continue; |
1150 | 0 | } |
1151 | | |
1152 | 2 | taintedLLVMNodes.insert(D); |
1153 | 2 | ValueToVisit.push(D); |
1154 | 2 | } |
1155 | 1 | } |
1156 | 4 | } |
1157 | | |
1158 | 9 | if (!ValueToVisit.empty()) { |
1159 | 9 | Value const *S = ValueToVisit.front(); |
1160 | 9 | ValueToVisit.pop(); |
1161 | | |
1162 | 9 | if (llvmToLLVMChildren.find(S) != llvmToLLVMChildren.end()) { |
1163 | 2 | for (Value const *D : llvmToLLVMChildren[S]) { |
1164 | 2 | if (taintedLLVMNodes.count(D) != 0) { |
1165 | 0 | continue; |
1166 | 0 | } |
1167 | | |
1168 | 2 | taintedLLVMNodes.insert(D); |
1169 | 2 | ValueToVisit.push(D); |
1170 | 2 | } |
1171 | 2 | } |
1172 | | |
1173 | 9 | if (llvmToSSAChildren.find(S) != llvmToSSAChildren.end()) { |
1174 | 2 | for (MSSAVar *D : llvmToSSAChildren[S]) { |
1175 | 2 | if (taintedSSANodes.count(D) != 0) { |
1176 | 0 | continue; |
1177 | 0 | } |
1178 | 2 | taintedSSANodes.insert(D); |
1179 | 2 | VarToVisit.push(D); |
1180 | 2 | } |
1181 | 2 | } |
1182 | 9 | } |
1183 | 9 | } |
1184 | | |
1185 | 9 | for (Value const *V : taintedLLVMNodes) { |
1186 | 9 | taintedConditions.insert(V); |
1187 | 9 | } |
1188 | | |
1189 | 1 | assert(FuncToLlvmNodesMapSize == funcToLLVMNodesMap.size()); |
1190 | 1 | assert(FuncToSsaNodesMapSize == funcToSSANodesMap.size()); |
1191 | 1 | assert(VarArgNodeSize == varArgNodes.size()); |
1192 | 1 | assert(LlvmToLlvmChildrenSize == llvmToLLVMChildren.size()); |
1193 | 1 | assert(LlvmToLlvmParentsSize == llvmToLLVMParents.size()); |
1194 | 1 | assert(LlvmToSsaChildrenSize == llvmToSSAChildren.size()); |
1195 | 1 | assert(LlvmToSsaParentsSize == llvmToSSAParents.size()); |
1196 | 1 | assert(SsaToLlvmChildrenSize == ssaToLLVMChildren.size()); |
1197 | 1 | assert(SsaToLlvmParentsSize == ssaToLLVMParents.size()); |
1198 | 1 | assert(SsaToSsaChildrenSize == ssaToSSAChildren.size()); |
1199 | 1 | assert(SsaToSsaParentsSize == ssaToSSAParents.size()); |
1200 | 1 | assert(FuncToCallNodesSize == funcToCallNodes.size()); |
1201 | 1 | assert(CallToFuncEdgesSize == callToFuncEdges.size()); |
1202 | 1 | assert(CondToCallEdgesSize == condToCallEdges.size()); |
1203 | 1 | assert(FuncToCallSitesSize == funcToCallSites.size()); |
1204 | 1 | assert(CallsiteToCondsSize == callsiteToConds.size()); |
1205 | 1 | } |
1206 | | |
1207 | 2.57k | bool DepGraphDCF::isTaintedValue(Value const *V) const { |
1208 | 2.57k | return taintedConditions.find(V) != taintedConditions.end(); |
1209 | 2.57k | } |
1210 | | |
1211 | | void DepGraphDCF::getCallInterIPDF( |
1212 | | llvm::CallInst const *Call, |
1213 | 6.87k | std::set<llvm::BasicBlock const *> &Ipdf) const { |
1214 | 6.87k | std::set<llvm::CallInst const *> VisitedCallSites; |
1215 | 6.87k | std::queue<CallInst const *> CallsitesToVisit; |
1216 | 6.87k | CallsitesToVisit.push(Call); |
1217 | | |
1218 | 13.8k | while (!CallsitesToVisit.empty()) { |
1219 | 6.95k | CallInst const *CS = CallsitesToVisit.front(); |
1220 | 6.95k | Function *F = const_cast<Function *>(CS->getParent()->getParent()); |
1221 | 6.95k | CallsitesToVisit.pop(); |
1222 | 6.95k | VisitedCallSites.insert(CS); |
1223 | | |
1224 | 6.95k | BasicBlock *BB = const_cast<BasicBlock *>(CS->getParent()); |
1225 | 6.95k | PostDominatorTree &PDT = FAM.getResult<PostDominatorTreeAnalysis>(*F); |
1226 | 6.95k | std::vector<BasicBlock *> FuncIpdf = |
1227 | 6.95k | iterated_postdominance_frontier(PDT, BB); |
1228 | 6.95k | Ipdf.insert(FuncIpdf.begin(), FuncIpdf.end()); |
1229 | 6.95k | auto It = funcToCallSites.find(F); |
1230 | 6.95k | if (It != funcToCallSites.end()) { |
1231 | 85 | for (Value const *V : It->second) { |
1232 | 85 | CallInst const *CS2 = cast<CallInst>(V); |
1233 | 85 | if (VisitedCallSites.count(CS2) != 0) { |
1234 | 0 | continue; |
1235 | 0 | } |
1236 | 85 | CallsitesToVisit.push(CS2); |
1237 | 85 | } |
1238 | 83 | } |
1239 | 6.95k | } |
1240 | 6.87k | } |
1241 | | |
1242 | 8.18k | bool DepGraphDCF::areSSANodesEquivalent(MSSAVar *Var1, MSSAVar *Var2) { |
1243 | 8.18k | assert(Var1); |
1244 | 8.18k | assert(Var2); |
1245 | | |
1246 | 8.18k | if (Var1->def->type == MSSADef::PHI || Var2->def->type == MSSADef::PHI) { |
1247 | 743 | return false; |
1248 | 743 | } |
1249 | | |
1250 | 7.44k | VarSet IncomingSsAsVar1; |
1251 | 7.44k | VarSet IncomingSsAsVar2; |
1252 | | |
1253 | 7.44k | ValueSet IncomingValuesVar1; |
1254 | 7.44k | ValueSet IncomingValuesVar2; |
1255 | | |
1256 | 7.44k | bool FoundVar1 = false; |
1257 | 7.44k | bool FoundVar2 = false; |
1258 | 7.44k | FoundVar1 = ssaToSSAChildren.find(Var1) != ssaToSSAChildren.end(); |
1259 | 7.44k | FoundVar2 = ssaToSSAChildren.find(Var2) != ssaToSSAChildren.end(); |
1260 | 7.44k | if (FoundVar1 != FoundVar2) { |
1261 | 0 | return false; |
1262 | 0 | } |
1263 | | |
1264 | | // Check whether number of edges are the same for both nodes. |
1265 | 7.44k | if (FoundVar1 && FoundVar2) { |
1266 | 7.44k | if (ssaToSSAChildren[Var1].size() != ssaToSSAChildren[Var2].size()) { |
1267 | 983 | return false; |
1268 | 983 | } |
1269 | 7.44k | } |
1270 | | |
1271 | 6.45k | FoundVar1 = ssaToLLVMChildren.find(Var1) != ssaToLLVMChildren.end(); |
1272 | 6.45k | FoundVar2 = ssaToLLVMChildren.find(Var2) != ssaToLLVMChildren.end(); |
1273 | 6.45k | if (FoundVar1 != FoundVar2) { |
1274 | 109 | return false; |
1275 | 109 | } |
1276 | 6.34k | if (FoundVar1 && FoundVar2) { |
1277 | 0 | if (ssaToLLVMChildren[Var1].size() != ssaToLLVMChildren[Var2].size()) { |
1278 | 0 | return false; |
1279 | 0 | } |
1280 | 0 | } |
1281 | | |
1282 | 6.34k | FoundVar1 = ssaToSSAParents.find(Var1) != ssaToSSAParents.end(); |
1283 | 6.34k | FoundVar2 = ssaToSSAParents.find(Var2) != ssaToSSAParents.end(); |
1284 | 6.34k | if (FoundVar1 != FoundVar2) { |
1285 | 1.30k | return false; |
1286 | 1.30k | } |
1287 | 5.04k | if (FoundVar1 && FoundVar2) { |
1288 | 4.46k | if (ssaToSSAParents[Var1].size() != ssaToSSAParents[Var2].size()) { |
1289 | 0 | return false; |
1290 | 0 | } |
1291 | 4.46k | } |
1292 | | |
1293 | 5.04k | FoundVar1 = ssaToLLVMParents.find(Var1) != ssaToLLVMParents.end(); |
1294 | 5.04k | FoundVar2 = ssaToLLVMParents.find(Var2) != ssaToLLVMParents.end(); |
1295 | 5.04k | if (FoundVar1 != FoundVar2) { |
1296 | 59 | return false; |
1297 | 59 | } |
1298 | 4.98k | if (FoundVar1 && FoundVar2) { |
1299 | 520 | if (ssaToLLVMParents[Var1].size() != ssaToLLVMParents[Var2].size()) { |
1300 | 0 | return false; |
1301 | 0 | } |
1302 | 520 | } |
1303 | | |
1304 | | // Check whether outgoing edges are the same for both nodes. |
1305 | 4.98k | if (ssaToSSAChildren.find(Var1) != ssaToSSAChildren.end()) { |
1306 | 4.99k | for (MSSAVar *V : ssaToSSAChildren[Var1]) { |
1307 | 4.99k | if (ssaToSSAChildren[Var2].find(V) == ssaToSSAChildren[Var2].end()) { |
1308 | 44 | return false; |
1309 | 44 | } |
1310 | 4.99k | } |
1311 | 4.98k | } |
1312 | 4.94k | if (ssaToLLVMChildren.find(Var1) != ssaToLLVMChildren.end()) { |
1313 | 0 | for (Value const *V : ssaToLLVMChildren[Var1]) { |
1314 | 0 | if (ssaToLLVMChildren[Var2].find(V) == ssaToLLVMChildren[Var2].end()) { |
1315 | 0 | return false; |
1316 | 0 | } |
1317 | 0 | } |
1318 | 0 | } |
1319 | | |
1320 | | // Check whether incoming edges are the same for both nodes. |
1321 | 4.94k | if (ssaToSSAParents.find(Var1) != ssaToSSAParents.end()) { |
1322 | 4.42k | for (MSSAVar *V : ssaToSSAParents[Var1]) { |
1323 | 4.42k | if (ssaToSSAParents[Var2].find(V) == ssaToSSAParents[Var2].end()) { |
1324 | 4.42k | return false; |
1325 | 4.42k | } |
1326 | 4.42k | } |
1327 | 4.42k | } |
1328 | 520 | if (ssaToLLVMParents.find(Var1) != ssaToLLVMParents.end()) { |
1329 | 897 | for (Value const *V : ssaToLLVMParents[Var1]) { |
1330 | 897 | if (ssaToLLVMParents[Var2].find(V) == ssaToLLVMParents[Var2].end()) { |
1331 | 512 | return false; |
1332 | 512 | } |
1333 | 897 | } |
1334 | 520 | } |
1335 | | |
1336 | 8 | return true; |
1337 | 520 | } |
1338 | | |
1339 | 8 | void DepGraphDCF::eliminatePhi(MSSAPhi *Phi, std::vector<MSSAVar *> Ops) { |
1340 | 8 | struct Ssa2SsaEdge { |
1341 | 16 | Ssa2SsaEdge(MSSAVar *S, MSSAVar *D) : S(S), D(D) {} |
1342 | 8 | MSSAVar *S; |
1343 | 8 | MSSAVar *D; |
1344 | 8 | }; |
1345 | 8 | struct Ssa2LlvmEdge { |
1346 | 8 | Ssa2LlvmEdge(MSSAVar *S, Value const *D) : S(S), D(D) {} |
1347 | 8 | MSSAVar *S; |
1348 | 8 | Value const *D; |
1349 | 8 | }; |
1350 | 8 | struct Llvm2SsaEdge { |
1351 | 16 | Llvm2SsaEdge(Value const *S, MSSAVar *D) : S(S), D(D) {} |
1352 | 8 | Value const *S; |
1353 | 8 | MSSAVar *D; |
1354 | 8 | }; |
1355 | 8 | struct Llvm2LlvmEdge { |
1356 | 8 | Llvm2LlvmEdge(Value const *S, Value const *D) : S(S), D(D) {} |
1357 | 8 | Value const *S; |
1358 | 8 | Value const *D; |
1359 | 8 | }; |
1360 | | |
1361 | | // Singlify operands |
1362 | 8 | std::set<MSSAVar *> OpsSet; |
1363 | 16 | for (MSSAVar *V : Ops) { |
1364 | 16 | OpsSet.insert(V); |
1365 | 16 | } |
1366 | 8 | Ops.clear(); |
1367 | 16 | for (MSSAVar *V : OpsSet) { |
1368 | 16 | Ops.push_back(V); |
1369 | 16 | } |
1370 | | |
1371 | | // Remove links from predicates to PHI |
1372 | 16 | for (Value const *V : Phi->preds) { |
1373 | 16 | removeEdge(V, Phi->var.get()); |
1374 | 16 | } |
1375 | | |
1376 | | // Remove links from ops to PHI |
1377 | 16 | for (MSSAVar *Op : Ops) { |
1378 | 16 | removeEdge(Op, Phi->var.get()); |
1379 | 16 | } |
1380 | | |
1381 | | // For each outgoing edge from PHI to a SSA node N, connect |
1382 | | // op1 to N and remove the link from PHI to N. |
1383 | 8 | { |
1384 | 8 | std::vector<Ssa2SsaEdge> EdgesToAdd; |
1385 | 8 | std::vector<Ssa2SsaEdge> EdgesToRemove; |
1386 | 8 | if (ssaToSSAChildren.find(Phi->var.get()) != ssaToSSAChildren.end()) { |
1387 | 8 | for (MSSAVar *V : ssaToSSAChildren[Phi->var.get()]) { |
1388 | 8 | EdgesToAdd.push_back(Ssa2SsaEdge(Ops[0], V)); |
1389 | 8 | EdgesToRemove.push_back(Ssa2SsaEdge(Phi->var.get(), V)); |
1390 | | |
1391 | | // If N is a phi replace the phi operand of N with op1 |
1392 | 8 | if (V->def->type == MSSADef::PHI) { |
1393 | 8 | MSSAPhi *OutPhi = cast<MSSAPhi>(V->def); |
1394 | | |
1395 | 8 | bool Found = false; |
1396 | 8 | for (auto &Entry : OutPhi->opsVar) { |
1397 | 8 | if (Entry.second == Phi->var.get()) { |
1398 | 8 | Found = true; |
1399 | 8 | Entry.second = Ops[0]; |
1400 | 8 | break; |
1401 | 8 | } |
1402 | 8 | } |
1403 | 8 | if (!Found) { |
1404 | 0 | continue; |
1405 | 0 | } |
1406 | 8 | assert(Found); |
1407 | 8 | } |
1408 | 8 | } |
1409 | 8 | } |
1410 | 8 | for (Ssa2SsaEdge E : EdgesToAdd) { |
1411 | 8 | addEdge(E.S, E.D); |
1412 | 8 | } |
1413 | 8 | for (Ssa2SsaEdge E : EdgesToRemove) { |
1414 | 8 | removeEdge(E.S, E.D); |
1415 | 8 | } |
1416 | 8 | } |
1417 | | |
1418 | 8 | { |
1419 | 8 | std::vector<Ssa2LlvmEdge> EdgesToAdd; |
1420 | 8 | std::vector<Ssa2LlvmEdge> EdgesToRemove; |
1421 | | |
1422 | | // For each outgoing edge from PHI to a LLVM node N, connect |
1423 | | // connect op1 to N and remove the link from PHI to N. |
1424 | 8 | if (ssaToLLVMChildren.find(Phi->var.get()) != ssaToLLVMChildren.end()) { |
1425 | 0 | for (Value const *V : ssaToLLVMChildren[Phi->var.get()]) { |
1426 | | // addEdge(ops[0], v); |
1427 | | // removeEdge(phi->var, v); |
1428 | 0 | EdgesToAdd.push_back(Ssa2LlvmEdge(Ops[0], V)); |
1429 | 0 | EdgesToRemove.push_back(Ssa2LlvmEdge(Phi->var.get(), V)); |
1430 | 0 | } |
1431 | 0 | } |
1432 | 8 | for (Ssa2LlvmEdge E : EdgesToAdd) { |
1433 | 0 | addEdge(E.S, E.D); |
1434 | 0 | } |
1435 | 8 | for (Ssa2LlvmEdge E : EdgesToRemove) { |
1436 | 0 | removeEdge(E.S, E.D); |
1437 | 0 | } |
1438 | 8 | } |
1439 | | |
1440 | | // Remove PHI Node |
1441 | 8 | Function const *F = Phi->var->bb->getParent(); |
1442 | 8 | assert(F); |
1443 | 8 | auto It = funcToSSANodesMap[F].find(Phi->var.get()); |
1444 | 8 | assert(It != funcToSSANodesMap[F].end()); |
1445 | 8 | funcToSSANodesMap[F].erase(It); |
1446 | | |
1447 | | // Remove edges connected to other operands than op0 |
1448 | 8 | { |
1449 | 8 | std::vector<Ssa2SsaEdge> ToRemove1; |
1450 | 8 | std::vector<Ssa2LlvmEdge> ToRemove2; |
1451 | 8 | std::vector<Llvm2SsaEdge> ToRemove3; |
1452 | 16 | for (unsigned I = 1; I < Ops.size(); ++I) { |
1453 | 8 | if (ssaToSSAParents.find(Ops[I]) != ssaToSSAParents.end()) { |
1454 | 0 | for (MSSAVar *V : ssaToSSAParents[Ops[I]]) { |
1455 | 0 | ToRemove1.push_back(Ssa2SsaEdge(V, Ops[I])); |
1456 | 0 | } |
1457 | 0 | } |
1458 | 8 | if (ssaToLLVMParents.find(Ops[I]) != ssaToLLVMParents.end()) { |
1459 | 16 | for (Value const *V : ssaToLLVMParents[Ops[I]]) { |
1460 | 16 | ToRemove3.push_back(Llvm2SsaEdge(V, Ops[I])); |
1461 | 16 | } |
1462 | 8 | } |
1463 | 8 | if (ssaToSSAChildren.find(Ops[I]) != ssaToSSAChildren.end()) { |
1464 | 8 | for (MSSAVar *V : ssaToSSAChildren[Ops[I]]) { |
1465 | 0 | ToRemove1.push_back(Ssa2SsaEdge(Ops[I], V)); |
1466 | 0 | } |
1467 | 8 | } |
1468 | 8 | if (ssaToLLVMChildren.find(Ops[I]) != ssaToLLVMChildren.end()) { |
1469 | 0 | for (Value const *V : ssaToLLVMChildren[Ops[I]]) { |
1470 | 0 | ToRemove2.push_back(Ssa2LlvmEdge(Ops[I], V)); |
1471 | 0 | } |
1472 | 0 | } |
1473 | 8 | } |
1474 | 8 | for (Ssa2SsaEdge E : ToRemove1) { |
1475 | 0 | removeEdge(E.S, E.D); |
1476 | 0 | } |
1477 | 8 | for (Ssa2LlvmEdge E : ToRemove2) { |
1478 | 0 | removeEdge(E.S, E.D); |
1479 | 0 | } |
1480 | 16 | for (Llvm2SsaEdge E : ToRemove3) { |
1481 | 16 | removeEdge(E.S, E.D); |
1482 | 16 | } |
1483 | 8 | } |
1484 | | |
1485 | | // Remove other operands than op 0 from the graph |
1486 | 16 | for (unsigned I = 1; I < Ops.size(); ++I) { |
1487 | 8 | auto It2 = funcToSSANodesMap[F].find(Ops[I]); |
1488 | 8 | assert(It2 != funcToSSANodesMap[F].end()); |
1489 | 8 | funcToSSANodesMap[F].erase(It2); |
1490 | 8 | } |
1491 | 8 | } |
1492 | | |
1493 | 1.76k | void DepGraphDCF::phiElimination() { |
1494 | | |
1495 | 1.76k | TimeTraceScope TTS("PhiElimination"); |
1496 | | |
1497 | | // For each function, iterate through its basic block and try to eliminate phi |
1498 | | // function until reaching a fixed point. |
1499 | 19.8k | for (Function const &F : M) { |
1500 | 19.8k | bool Changed = true; |
1501 | | |
1502 | 39.7k | while (Changed) { |
1503 | 19.8k | Changed = false; |
1504 | | |
1505 | 19.8k | for (BasicBlock const &BB : F) { |
1506 | 15.3k | for (auto const &Phi : getRange(mssa->getBBToPhiMap(), &BB)) { |
1507 | | |
1508 | 8.19k | assert(funcToSSANodesMap.find(&F) != funcToSSANodesMap.end()); |
1509 | | |
1510 | | // Has the phi node been removed already ? |
1511 | 8.19k | if (funcToSSANodesMap[&F].count(Phi->var.get()) == 0) { |
1512 | 8 | continue; |
1513 | 8 | } |
1514 | | |
1515 | | // For each phi we test if its operands (chi) are not PHI and |
1516 | | // are equivalent |
1517 | 8.18k | std::vector<MSSAVar *> PhiOperands; |
1518 | 16.4k | for (auto J : Phi->opsVar) { |
1519 | 16.4k | PhiOperands.push_back(J.second); |
1520 | 16.4k | } |
1521 | | |
1522 | 8.18k | bool CanElim = true; |
1523 | 8.19k | for (unsigned I = 0; I < PhiOperands.size() - 1; I++) { |
1524 | 8.18k | if (!areSSANodesEquivalent(PhiOperands[I], PhiOperands[I + 1])) { |
1525 | 8.17k | CanElim = false; |
1526 | 8.17k | break; |
1527 | 8.17k | } |
1528 | 8.18k | } |
1529 | 8.18k | if (!CanElim) { |
1530 | 8.17k | continue; |
1531 | 8.17k | } |
1532 | | |
1533 | | // PHI Node can be eliminated ! |
1534 | 8 | Changed = true; |
1535 | 8 | eliminatePhi(Phi.get(), PhiOperands); |
1536 | 8 | } |
1537 | 15.3k | } |
1538 | 19.8k | } |
1539 | 19.8k | } |
1540 | 1.76k | } |
1541 | | |
1542 | 80.4k | void DepGraphDCF::addEdge(llvm::Value const *S, llvm::Value const *D) { |
1543 | 80.4k | llvmToLLVMChildren[S].insert(D); |
1544 | 80.4k | llvmToLLVMParents[D].insert(S); |
1545 | 80.4k | } |
1546 | | |
1547 | 334k | void DepGraphDCF::addEdge(llvm::Value const *S, MSSAVar *D) { |
1548 | 334k | llvmToSSAChildren[S].insert(D); |
1549 | 334k | ssaToLLVMParents[D].insert(S); |
1550 | 334k | } |
1551 | | |
1552 | 43.9k | void DepGraphDCF::addEdge(MSSAVar *S, llvm::Value const *D) { |
1553 | 43.9k | ssaToLLVMChildren[S].insert(D); |
1554 | 43.9k | llvmToSSAParents[D].insert(S); |
1555 | 43.9k | } |
1556 | | |
1557 | 385k | void DepGraphDCF::addEdge(MSSAVar *S, MSSAVar *D) { |
1558 | 385k | ssaToSSAChildren[S].insert(D); |
1559 | 385k | ssaToSSAParents[D].insert(S); |
1560 | 385k | } |
1561 | | |
1562 | 0 | void DepGraphDCF::removeEdge(llvm::Value const *S, llvm::Value const *D) { |
1563 | 0 | int N; |
1564 | 0 | N = llvmToLLVMChildren[S].erase(D); |
1565 | 0 | assert(N == 1); |
1566 | 0 | N = llvmToLLVMParents[D].erase(S); |
1567 | 0 | assert(N == 1); |
1568 | 0 | (void)N; |
1569 | 0 | } |
1570 | | |
1571 | 32 | void DepGraphDCF::removeEdge(llvm::Value const *S, MSSAVar *D) { |
1572 | 32 | int N; |
1573 | 32 | N = llvmToSSAChildren[S].erase(D); |
1574 | 32 | assert(N == 1); |
1575 | 32 | N = ssaToLLVMParents[D].erase(S); |
1576 | 32 | assert(N == 1); |
1577 | 32 | (void)N; |
1578 | 32 | } |
1579 | | |
1580 | 0 | void DepGraphDCF::removeEdge(MSSAVar *S, llvm::Value const *D) { |
1581 | 0 | int N; |
1582 | 0 | N = ssaToLLVMChildren[S].erase(D); |
1583 | 0 | assert(N == 1); |
1584 | 0 | N = llvmToSSAParents[D].erase(S); |
1585 | 0 | assert(N == 1); |
1586 | 0 | (void)N; |
1587 | 0 | } |
1588 | | |
1589 | 24 | void DepGraphDCF::removeEdge(MSSAVar *S, MSSAVar *D) { |
1590 | 24 | int N; |
1591 | 24 | N = ssaToSSAChildren[S].erase(D); |
1592 | 24 | assert(N == 1); |
1593 | 24 | N = ssaToSSAParents[D].erase(S); |
1594 | 24 | assert(N == 1); |
1595 | 24 | (void)N; |
1596 | 24 | } |
1597 | | |
1598 | | void DepGraphDCF::dotTaintPath(Value const *V, StringRef Filename, |
1599 | 1 | Instruction const *Collective) const { |
1600 | 1 | errs() << "Writing '" << Filename << "' ...\n"; |
1601 | | |
1602 | | // Parcours en largeur |
1603 | 1 | unsigned CurDist = 0; |
1604 | 1 | unsigned CurSize = 128; |
1605 | 1 | std::vector<std::set<Value const *>> VisitedLlvmNodesByDist; |
1606 | 1 | std::set<Value const *> VisitedLlvmNodes; |
1607 | 1 | std::vector<std::set<MSSAVar *>> VisitedSsaNodesByDist; |
1608 | 1 | std::set<MSSAVar *> VisitedSsaNodes; |
1609 | | |
1610 | 1 | VisitedSsaNodesByDist.resize(CurSize); |
1611 | 1 | VisitedLlvmNodesByDist.resize(CurSize); |
1612 | | |
1613 | 1 | VisitedLlvmNodes.insert(V); |
1614 | | |
1615 | 2 | for (Value const *P : getRange(llvmToLLVMParents, V)) { |
1616 | 2 | if (VisitedLlvmNodes.find(P) != VisitedLlvmNodes.end()) { |
1617 | 0 | continue; |
1618 | 0 | } |
1619 | | |
1620 | 2 | if (taintedLLVMNodes.find(P) == taintedLLVMNodes.end()) { |
1621 | 1 | continue; |
1622 | 1 | } |
1623 | | |
1624 | 1 | VisitedLlvmNodesByDist[CurDist].insert(P); |
1625 | 1 | } |
1626 | 1 | for (MSSAVar *P : getRange(llvmToSSAParents, V)) { |
1627 | 0 | if (VisitedSsaNodes.find(P) != VisitedSsaNodes.end()) { |
1628 | 0 | continue; |
1629 | 0 | } |
1630 | | |
1631 | 0 | if (taintedSSANodes.find(P) == taintedSSANodes.end()) { |
1632 | 0 | continue; |
1633 | 0 | } |
1634 | | |
1635 | 0 | VisitedSsaNodesByDist[CurDist].insert(P); |
1636 | 0 | } |
1637 | | |
1638 | 1 | bool Stop = false; |
1639 | 1 | MSSAVar *SsaRoot = NULL; |
1640 | 1 | Value const *LlvmRoot = NULL; |
1641 | | |
1642 | 4 | while (true) { |
1643 | 4 | if (CurDist >= CurSize) { |
1644 | 0 | CurSize *= 2; |
1645 | 0 | VisitedLlvmNodesByDist.resize(CurSize); |
1646 | 0 | VisitedSsaNodesByDist.resize(CurSize); |
1647 | 0 | } |
1648 | | |
1649 | | // Visit parents of llvm values |
1650 | 4 | for (Value const *V : VisitedLlvmNodesByDist[CurDist]) { |
1651 | 3 | if (valueSources.find(V) != valueSources.end()) { |
1652 | 1 | LlvmRoot = V; |
1653 | 1 | VisitedLlvmNodes.insert(V); |
1654 | 1 | errs() << "found a path of size " << CurDist << "\n"; |
1655 | 1 | Stop = true; |
1656 | 1 | break; |
1657 | 1 | } |
1658 | | |
1659 | 2 | VisitedLlvmNodes.insert(V); |
1660 | | |
1661 | 3 | for (Value const *P : getRange(llvmToLLVMParents, V)) { |
1662 | 3 | if (VisitedLlvmNodes.find(P) != VisitedLlvmNodes.end()) { |
1663 | 0 | continue; |
1664 | 0 | } |
1665 | | |
1666 | 3 | if (taintedLLVMNodes.find(P) == taintedLLVMNodes.end()) { |
1667 | 2 | continue; |
1668 | 2 | } |
1669 | | |
1670 | 1 | VisitedLlvmNodesByDist[CurDist + 1].insert(P); |
1671 | 1 | } |
1672 | 2 | for (MSSAVar *P : getRange(llvmToSSAParents, V)) { |
1673 | 1 | if (VisitedSsaNodes.find(P) != VisitedSsaNodes.end()) { |
1674 | 0 | continue; |
1675 | 0 | } |
1676 | | |
1677 | 1 | if (taintedSSANodes.find(P) == taintedSSANodes.end()) { |
1678 | 0 | continue; |
1679 | 0 | } |
1680 | | |
1681 | 1 | VisitedSsaNodesByDist[CurDist + 1].insert(P); |
1682 | 1 | } |
1683 | 2 | } |
1684 | | |
1685 | 4 | if (Stop) { |
1686 | 1 | break; |
1687 | 1 | } |
1688 | | |
1689 | | // Visit parents of ssa variables |
1690 | 3 | for (MSSAVar *V : VisitedSsaNodesByDist[CurDist]) { |
1691 | 1 | if (ssaSources.find(V) != ssaSources.end()) { |
1692 | 0 | SsaRoot = V; |
1693 | 0 | VisitedSsaNodes.insert(V); |
1694 | 0 | errs() << "found a path of size " << CurDist << "\n"; |
1695 | 0 | Stop = true; |
1696 | 0 | break; |
1697 | 0 | } |
1698 | | |
1699 | 1 | VisitedSsaNodes.insert(V); |
1700 | 2 | for (Value const *P : getRange(ssaToLLVMParents, V)) { |
1701 | 2 | if (VisitedLlvmNodes.find(P) != VisitedLlvmNodes.end()) { |
1702 | 0 | continue; |
1703 | 0 | } |
1704 | | |
1705 | 2 | if (taintedLLVMNodes.find(P) == taintedLLVMNodes.end()) { |
1706 | 1 | continue; |
1707 | 1 | } |
1708 | | |
1709 | 1 | VisitedLlvmNodesByDist[CurDist + 1].insert(P); |
1710 | 1 | } |
1711 | 1 | for (MSSAVar *P : getRange(ssaToSSAParents, V)) { |
1712 | 0 | if (VisitedSsaNodes.find(P) != VisitedSsaNodes.end()) { |
1713 | 0 | continue; |
1714 | 0 | } |
1715 | | |
1716 | 0 | if (taintedSSANodes.find(P) == taintedSSANodes.end()) { |
1717 | 0 | continue; |
1718 | 0 | } |
1719 | | |
1720 | 0 | VisitedSsaNodesByDist[CurDist + 1].insert(P); |
1721 | 0 | } |
1722 | | |
1723 | 1 | if (Stop) { |
1724 | 0 | break; |
1725 | 0 | } |
1726 | 1 | } |
1727 | | |
1728 | 3 | if (Stop) { |
1729 | 0 | break; |
1730 | 0 | } |
1731 | | |
1732 | 3 | CurDist++; |
1733 | 3 | } |
1734 | | |
1735 | 1 | assert(Stop); |
1736 | | |
1737 | 1 | std::error_code EC; |
1738 | 1 | raw_fd_ostream Stream(Filename, EC, sys::fs::OF_Text); |
1739 | | |
1740 | 1 | Stream << "digraph F {\n"; |
1741 | 1 | Stream << "compound=true;\n"; |
1742 | 1 | Stream << "rankdir=LR;\n"; |
1743 | | |
1744 | 1 | std::vector<std::string> DebugMsgs; |
1745 | 1 | std::vector<DGDebugLoc> DebugLocs; |
1746 | | |
1747 | 1 | VisitedSsaNodes.clear(); |
1748 | 1 | VisitedLlvmNodes.clear(); |
1749 | | |
1750 | 1 | assert(LlvmRoot || SsaRoot); |
1751 | | |
1752 | 1 | if (SsaRoot) { |
1753 | 0 | VisitedSsaNodes.insert(SsaRoot); |
1754 | 1 | } else { |
1755 | 1 | VisitedLlvmNodes.insert(LlvmRoot); |
1756 | 1 | } |
1757 | | |
1758 | 1 | std::string TmpStr; |
1759 | 1 | raw_string_ostream StrStream(TmpStr); |
1760 | | |
1761 | 1 | MSSAVar *LastVar = SsaRoot; |
1762 | 1 | Value const *LastValue = LlvmRoot; |
1763 | 1 | DGDebugLoc DL; |
1764 | | |
1765 | 1 | if (LastVar) { |
1766 | 0 | DebugMsgs.push_back(getStringMsg(LastVar)); |
1767 | |
|
1768 | 0 | if (getDGDebugLoc(LastVar, DL)) { |
1769 | 0 | DebugLocs.push_back(DL); |
1770 | 0 | } |
1771 | 1 | } else { |
1772 | 1 | DebugMsgs.push_back(getStringMsg(LastValue)); |
1773 | 1 | if (getDGDebugLoc(LastValue, DL)) { |
1774 | 1 | DebugLocs.push_back(DL); |
1775 | 1 | } |
1776 | 1 | } |
1777 | | |
1778 | 1 | bool LastIsVar = LastVar != NULL; |
1779 | | |
1780 | | // Compute edges of the shortest path to strStream |
1781 | 3 | for (unsigned I = CurDist - 1; I > 0; I--) { |
1782 | 2 | bool Found = false; |
1783 | 2 | if (LastIsVar) { |
1784 | 0 | for (MSSAVar *V : VisitedSsaNodesByDist[I]) { |
1785 | 0 | if (count(getRange(ssaToSSAParents, V), LastVar) == 0) { |
1786 | 0 | continue; |
1787 | 0 | } |
1788 | | |
1789 | 0 | VisitedSsaNodes.insert(V); |
1790 | 0 | StrStream << "Node" << ((void *)LastVar) << " -> " |
1791 | 0 | << "Node" << ((void *)V) << "\n"; |
1792 | 0 | LastVar = V; |
1793 | 0 | Found = true; |
1794 | 0 | DebugMsgs.push_back(getStringMsg(V)); |
1795 | 0 | if (getDGDebugLoc(V, DL)) { |
1796 | 0 | DebugLocs.push_back(DL); |
1797 | 0 | } |
1798 | 0 | break; |
1799 | 0 | } |
1800 | |
|
1801 | 0 | if (Found) { |
1802 | 0 | continue; |
1803 | 0 | } |
1804 | | |
1805 | 0 | for (Value const *V : VisitedLlvmNodesByDist[I]) { |
1806 | 0 | if (count(getRange(llvmToSSAParents, V), LastVar) == 0) { |
1807 | 0 | continue; |
1808 | 0 | } |
1809 | | |
1810 | 0 | VisitedLlvmNodes.insert(V); |
1811 | 0 | StrStream << "Node" << ((void *)LastVar) << " -> " |
1812 | 0 | << "Node" << ((void *)V) << "\n"; |
1813 | 0 | LastValue = V; |
1814 | 0 | LastIsVar = false; |
1815 | 0 | Found = true; |
1816 | 0 | DebugMsgs.push_back(getStringMsg(V)); |
1817 | 0 | if (getDGDebugLoc(V, DL)) { |
1818 | 0 | DebugLocs.push_back(DL); |
1819 | 0 | } |
1820 | 0 | break; |
1821 | 0 | } |
1822 | |
|
1823 | 0 | assert(Found); |
1824 | 0 | } |
1825 | | |
1826 | | // Last visited is a value |
1827 | 2 | else { |
1828 | 2 | for (MSSAVar *V : VisitedSsaNodesByDist[I]) { |
1829 | 1 | if (count(getRange(ssaToLLVMParents, V), LastValue) == 0) { |
1830 | 0 | continue; |
1831 | 0 | } |
1832 | | |
1833 | 1 | VisitedSsaNodes.insert(V); |
1834 | 1 | StrStream << "Node" << ((void *)LastValue) << " -> " |
1835 | 1 | << "Node" << ((void *)V) << "\n"; |
1836 | 1 | LastVar = V; |
1837 | 1 | LastIsVar = true; |
1838 | 1 | Found = true; |
1839 | 1 | DebugMsgs.push_back(getStringMsg(V)); |
1840 | 1 | if (getDGDebugLoc(V, DL)) { |
1841 | 1 | DebugLocs.push_back(DL); |
1842 | 1 | } |
1843 | 1 | break; |
1844 | 1 | } |
1845 | | |
1846 | 2 | if (Found) { |
1847 | 1 | continue; |
1848 | 1 | } |
1849 | | |
1850 | 1 | for (Value const *V : VisitedLlvmNodesByDist[I]) { |
1851 | 1 | if (count(getRange(llvmToLLVMParents, V), LastValue) == 0) { |
1852 | 0 | continue; |
1853 | 0 | } |
1854 | | |
1855 | 1 | VisitedLlvmNodes.insert(V); |
1856 | 1 | StrStream << "Node" << ((void *)LastValue) << " -> " |
1857 | 1 | << "Node" << ((void *)V) << "\n"; |
1858 | 1 | LastValue = V; |
1859 | 1 | LastIsVar = false; |
1860 | 1 | Found = true; |
1861 | 1 | DebugMsgs.push_back(getStringMsg(V)); |
1862 | 1 | if (getDGDebugLoc(V, DL)) { |
1863 | 1 | DebugLocs.push_back(DL); |
1864 | 1 | } |
1865 | 1 | break; |
1866 | 1 | } |
1867 | | |
1868 | 1 | assert(Found); |
1869 | 1 | } |
1870 | 2 | } |
1871 | | |
1872 | | // compute visited functions |
1873 | 1 | std::set<Function const *> VisitedFunctions; |
1874 | 3 | for (auto I : funcToLLVMNodesMap) { |
1875 | 36 | for (Value const *V : I.second) { |
1876 | 36 | if (VisitedLlvmNodes.find(V) != VisitedLlvmNodes.end()) { |
1877 | 2 | VisitedFunctions.insert(I.first); |
1878 | 2 | } |
1879 | 36 | } |
1880 | 3 | } |
1881 | | |
1882 | 5 | for (auto I : funcToSSANodesMap) { |
1883 | 57 | for (MSSAVar *V : I.second) { |
1884 | 57 | if (VisitedSsaNodes.find(V) != VisitedSsaNodes.end()) { |
1885 | 1 | VisitedFunctions.insert(I.first); |
1886 | 1 | } |
1887 | 57 | } |
1888 | 5 | } |
1889 | | |
1890 | | // Dot visited functions and nodes |
1891 | 1 | for (Function const *F : VisitedFunctions) { |
1892 | 1 | Stream << "\tsubgraph cluster_" << ((void *)F) << " {\n"; |
1893 | 1 | Stream << "style=filled;\ncolor=lightgrey;\n"; |
1894 | 1 | Stream << "label=< <B>" << F->getName() << "</B> >;\n"; |
1895 | 1 | Stream << "node [style=filled,color=white];\n"; |
1896 | | |
1897 | 2 | for (Value const *V : VisitedLlvmNodes) { |
1898 | 2 | if (count(getRange(funcToLLVMNodesMap, F), V) == 0) { |
1899 | 0 | continue; |
1900 | 0 | } |
1901 | | |
1902 | 2 | Stream << "Node" << ((void *)V) << " [label=\"" << getValueLabel(V) |
1903 | 2 | << "\" " << getNodeStyle(V) << "];\n"; |
1904 | 2 | } |
1905 | | |
1906 | 1 | for (MSSAVar *V : VisitedSsaNodes) { |
1907 | 1 | if (count(getRange(funcToSSANodesMap, F), V) == 0) { |
1908 | 0 | continue; |
1909 | 0 | } |
1910 | | |
1911 | 1 | Stream << "Node" << ((void *)V) << " [label=\"" << V->getName() |
1912 | 1 | << "\" shape=diamond " << getNodeStyle(V) << "];\n"; |
1913 | 1 | } |
1914 | | |
1915 | 1 | Stream << "}\n"; |
1916 | 1 | } |
1917 | | |
1918 | | // Dot edges |
1919 | 1 | Stream << StrStream.str(); |
1920 | | |
1921 | 1 | Stream << "}\n"; |
1922 | | |
1923 | 3 | for (auto const &Msg : DebugMsgs) { |
1924 | 3 | Stream << Msg; |
1925 | 3 | } |
1926 | | |
1927 | | // Write trace |
1928 | 1 | std::string Trace; |
1929 | 1 | if (getDebugTrace(DebugLocs, Trace, Collective)) { |
1930 | 1 | std::string Tracefilename = (Filename + ".trace").str(); |
1931 | 1 | errs() << "Writing '" << Tracefilename << "' ...\n"; |
1932 | 1 | raw_fd_ostream Tracestream(Tracefilename, EC, sys::fs::OF_Text); |
1933 | 1 | Tracestream << Trace; |
1934 | 1 | } |
1935 | 1 | } |
1936 | | |
1937 | 2 | std::string DepGraphDCF::getStringMsg(Value const *V) { |
1938 | 2 | std::string Msg; |
1939 | 2 | Msg.append("# "); |
1940 | 2 | Msg.append(getValueLabel(V)); |
1941 | 2 | Msg.append(":\n# "); |
1942 | | |
1943 | 2 | DebugLoc Loc = NULL; |
1944 | 2 | std::string FuncName = "unknown"; |
1945 | 2 | Instruction const *Inst = dyn_cast<Instruction>(V); |
1946 | 2 | if (Inst) { |
1947 | 2 | Loc = Inst->getDebugLoc(); |
1948 | 2 | FuncName = Inst->getParent()->getParent()->getName().str(); |
1949 | 2 | } |
1950 | | |
1951 | 2 | Msg.append("function: "); |
1952 | 2 | Msg.append(FuncName); |
1953 | 2 | if (Loc) { |
1954 | 2 | Msg.append(" file "); |
1955 | 2 | Msg.append(Loc->getFilename().str()); |
1956 | 2 | Msg.append(" line "); |
1957 | 2 | Msg.append(std::to_string(Loc.getLine())); |
1958 | 2 | } else { |
1959 | 0 | Msg.append(" no debug loc"); |
1960 | 0 | } |
1961 | 2 | Msg.append("\n"); |
1962 | | |
1963 | 2 | return Msg; |
1964 | 2 | } |
1965 | | |
1966 | 1 | std::string DepGraphDCF::getStringMsg(MSSAVar *V) { |
1967 | 1 | std::string Msg; |
1968 | 1 | Msg.append("# "); |
1969 | 1 | Msg.append(V->getName()); |
1970 | 1 | Msg.append(":\n# "); |
1971 | 1 | std::string FuncName = "unknown"; |
1972 | 1 | if (V->bb) { |
1973 | 1 | FuncName = V->bb->getParent()->getName().str(); |
1974 | 1 | } |
1975 | | |
1976 | 1 | MSSADef *Def = V->def; |
1977 | 1 | assert(Def); |
1978 | | |
1979 | | // Def can be PHI, call, store, chi, entry, extvararg, extarg, extret, |
1980 | | // extcall, extretcall |
1981 | | |
1982 | 1 | DebugLoc Loc = NULL; |
1983 | | |
1984 | 1 | if (isa<MSSACallChi>(Def)) { |
1985 | 0 | MSSACallChi *CallChi = cast<MSSACallChi>(Def); |
1986 | 0 | FuncName = CallChi->inst->getParent()->getParent()->getName().str(); |
1987 | 0 | Loc = CallChi->inst->getDebugLoc(); |
1988 | 1 | } else if (isa<MSSAStoreChi>(Def)) { |
1989 | 1 | MSSAStoreChi *StoreChi = cast<MSSAStoreChi>(Def); |
1990 | 1 | FuncName = StoreChi->inst->getParent()->getParent()->getName().str(); |
1991 | 1 | Loc = StoreChi->inst->getDebugLoc(); |
1992 | 1 | } else if (isa<MSSAExtCallChi>(Def)) { |
1993 | 0 | MSSAExtCallChi *ExtCallChi = cast<MSSAExtCallChi>(Def); |
1994 | 0 | FuncName = ExtCallChi->inst->getParent()->getParent()->getName().str(); |
1995 | 0 | Loc = ExtCallChi->inst->getDebugLoc(); |
1996 | 0 | } else if (isa<MSSAExtVarArgChi>(Def)) { |
1997 | 0 | MSSAExtVarArgChi *VarArgChi = cast<MSSAExtVarArgChi>(Def); |
1998 | 0 | FuncName = VarArgChi->func->getName().str(); |
1999 | 0 | } else if (isa<MSSAExtArgChi>(Def)) { |
2000 | 0 | MSSAExtArgChi *ExtArgChi = cast<MSSAExtArgChi>(Def); |
2001 | 0 | FuncName = ExtArgChi->func->getName().str(); |
2002 | 0 | } else if (isa<MSSAExtRetChi>(Def)) { |
2003 | 0 | MSSAExtRetChi *ExtRetChi = cast<MSSAExtRetChi>(Def); |
2004 | 0 | FuncName = ExtRetChi->func->getName().str(); |
2005 | 0 | } |
2006 | | |
2007 | 1 | Msg.append("function: "); |
2008 | 1 | Msg.append(FuncName); |
2009 | | |
2010 | 1 | if (Loc) { |
2011 | 1 | Msg.append(" file "); |
2012 | 1 | Msg.append(Loc->getFilename().str()); |
2013 | 1 | Msg.append(" line "); |
2014 | 1 | Msg.append(std::to_string(Loc.getLine())); |
2015 | 1 | } else { |
2016 | 0 | Msg.append(" no debug loc"); |
2017 | 0 | } |
2018 | 1 | Msg.append("\n"); |
2019 | | |
2020 | 1 | return Msg; |
2021 | 1 | } |
2022 | | |
2023 | 3 | bool DepGraphDCF::getDGDebugLoc(Value const *V, DGDebugLoc &DL) { |
2024 | 3 | DL.F = NULL; |
2025 | 3 | DL.line = -1; |
2026 | 3 | DL.filename = "unknown"; |
2027 | | |
2028 | 3 | DebugLoc Loc = NULL; |
2029 | | |
2030 | 3 | Instruction const *Inst = dyn_cast<Instruction>(V); |
2031 | 3 | if (Inst) { |
2032 | 3 | Loc = Inst->getDebugLoc(); |
2033 | 3 | DL.F = Inst->getParent()->getParent(); |
2034 | 3 | } |
2035 | | |
2036 | 3 | if (Loc) { |
2037 | 3 | DL.filename = Loc->getFilename().str(); |
2038 | 3 | DL.line = Loc->getLine(); |
2039 | 3 | } else { |
2040 | 0 | return false; |
2041 | 0 | } |
2042 | | |
2043 | 3 | return DL.F != NULL; |
2044 | 3 | } |
2045 | | |
2046 | 1 | bool DepGraphDCF::getDGDebugLoc(MSSAVar *V, DGDebugLoc &DL) { |
2047 | 1 | DL.F = NULL; |
2048 | 1 | DL.line = -1; |
2049 | 1 | DL.filename = "unknown"; |
2050 | | |
2051 | 1 | if (V->bb) { |
2052 | 1 | DL.F = V->bb->getParent(); |
2053 | 1 | } |
2054 | | |
2055 | 1 | MSSADef *Def = V->def; |
2056 | 1 | assert(Def); |
2057 | | |
2058 | | // Def can be PHI, call, store, chi, entry, extvararg, extarg, extret, |
2059 | | // extcall, extretcall |
2060 | | |
2061 | 1 | DebugLoc Loc = NULL; |
2062 | | |
2063 | 1 | if (isa<MSSACallChi>(Def)) { |
2064 | 0 | MSSACallChi *CallChi = cast<MSSACallChi>(Def); |
2065 | 0 | DL.F = CallChi->inst->getParent()->getParent(); |
2066 | 0 | Loc = CallChi->inst->getDebugLoc(); |
2067 | 1 | } else if (isa<MSSAStoreChi>(Def)) { |
2068 | 1 | MSSAStoreChi *StoreChi = cast<MSSAStoreChi>(Def); |
2069 | 1 | DL.F = StoreChi->inst->getParent()->getParent(); |
2070 | 1 | Loc = StoreChi->inst->getDebugLoc(); |
2071 | 1 | } else if (isa<MSSAExtCallChi>(Def)) { |
2072 | 0 | MSSAExtCallChi *ExtCallChi = cast<MSSAExtCallChi>(Def); |
2073 | 0 | DL.F = ExtCallChi->inst->getParent()->getParent(); |
2074 | 0 | Loc = ExtCallChi->inst->getDebugLoc(); |
2075 | 0 | } else if (isa<MSSAExtVarArgChi>(Def)) { |
2076 | 0 | MSSAExtVarArgChi *VarArgChi = cast<MSSAExtVarArgChi>(Def); |
2077 | 0 | DL.F = VarArgChi->func; |
2078 | 0 | } else if (isa<MSSAExtArgChi>(Def)) { |
2079 | 0 | MSSAExtArgChi *ExtArgChi = cast<MSSAExtArgChi>(Def); |
2080 | 0 | DL.F = ExtArgChi->func; |
2081 | 0 | } else if (isa<MSSAExtRetChi>(Def)) { |
2082 | 0 | MSSAExtRetChi *ExtRetChi = cast<MSSAExtRetChi>(Def); |
2083 | 0 | DL.F = ExtRetChi->func; |
2084 | 0 | } |
2085 | | |
2086 | 1 | if (Loc) { |
2087 | 1 | DL.filename = Loc->getFilename().str(); |
2088 | 1 | DL.line = Loc->getLine(); |
2089 | 1 | } else { |
2090 | 0 | return false; |
2091 | 0 | } |
2092 | | |
2093 | 1 | return DL.F != NULL; |
2094 | 1 | } |
2095 | | |
2096 | 3 | static bool getStrLine(std::ifstream &File, int Line, std::string &Str) { |
2097 | | // go to line |
2098 | 3 | File.seekg(std::ios::beg); |
2099 | 60 | for (int I = 0; I < Line - 1; ++I) { |
2100 | 57 | File.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); |
2101 | 57 | } |
2102 | | |
2103 | 3 | getline(File, Str); |
2104 | | |
2105 | 3 | return true; |
2106 | 3 | } |
2107 | | |
2108 | 1 | void DepGraphDCF::reorderAndRemoveDup(std::vector<DGDebugLoc> &DLs) { |
2109 | 1 | std::vector<DGDebugLoc> SameFuncDl; |
2110 | 1 | std::vector<DGDebugLoc> Res; |
2111 | | |
2112 | 1 | if (DLs.empty()) { |
2113 | 0 | return; |
2114 | 0 | } |
2115 | | |
2116 | 1 | Function const *Prev = DLs[0].F; |
2117 | 5 | while (!DLs.empty()) { |
2118 | | // pop front |
2119 | 4 | DGDebugLoc DL = DLs.front(); |
2120 | 4 | DLs.erase(DLs.begin()); |
2121 | | |
2122 | | // new function or end |
2123 | 4 | if (DL.F != Prev || DLs.empty()) { |
2124 | 1 | if (!DLs.empty()) { |
2125 | 0 | DLs.insert(DLs.begin(), DL); |
2126 | 1 | } else { |
2127 | 1 | SameFuncDl.push_back(DL); |
2128 | 1 | } |
2129 | | |
2130 | 1 | Prev = DL.F; |
2131 | | |
2132 | | // sort |
2133 | 1 | std::sort(SameFuncDl.begin(), SameFuncDl.end()); |
2134 | | |
2135 | | // remove duplicates |
2136 | 1 | int LinePrev = -1; |
2137 | 5 | for (unsigned I = 0; I < SameFuncDl.size(); ++I) { |
2138 | 4 | if (SameFuncDl[I].line == LinePrev) { |
2139 | 2 | LinePrev = SameFuncDl[I].line; |
2140 | 2 | SameFuncDl.erase(SameFuncDl.begin() + I); |
2141 | 2 | I--; |
2142 | 2 | } else { |
2143 | 2 | LinePrev = SameFuncDl[I].line; |
2144 | 2 | } |
2145 | 4 | } |
2146 | | |
2147 | | // append to res |
2148 | 1 | Res.insert(Res.end(), SameFuncDl.begin(), SameFuncDl.end()); |
2149 | 1 | SameFuncDl.clear(); |
2150 | 3 | } else { |
2151 | 3 | SameFuncDl.push_back(DL); |
2152 | 3 | } |
2153 | 4 | } |
2154 | | |
2155 | 1 | DLs.clear(); |
2156 | 1 | DLs.insert(DLs.begin(), Res.begin(), Res.end()); |
2157 | 1 | } |
2158 | | |
2159 | | bool DepGraphDCF::getDebugTrace(std::vector<DGDebugLoc> &DLs, |
2160 | | std::string &Trace, |
2161 | 1 | Instruction const *Collective) { |
2162 | 1 | DGDebugLoc CollectiveLoc; |
2163 | 1 | if (getDGDebugLoc(Collective, CollectiveLoc)) { |
2164 | 1 | DLs.push_back(CollectiveLoc); |
2165 | 1 | } |
2166 | | |
2167 | 1 | Function const *PrevFunc = NULL; |
2168 | 1 | std::ifstream File; |
2169 | | |
2170 | 1 | reorderAndRemoveDup(DLs); |
2171 | | |
2172 | 3 | for (unsigned I = 0; I < DLs.size(); ++I) { |
2173 | 2 | std::string Strline; |
2174 | 2 | Function const *F = DLs[I].F; |
2175 | 2 | if (!F) { |
2176 | 0 | return false; |
2177 | 0 | } |
2178 | | |
2179 | | // new function, print filename and protoype |
2180 | 2 | if (F != PrevFunc) { |
2181 | 1 | File.close(); |
2182 | 1 | PrevFunc = F; |
2183 | 1 | DISubprogram *DI = F->getSubprogram(); |
2184 | 1 | if (!DI) { |
2185 | 0 | return false; |
2186 | 0 | } |
2187 | | |
2188 | 1 | std::string Filename = DI->getFilename().str(); |
2189 | 1 | std::string Dir = DI->getDirectory().str(); |
2190 | 1 | std::string Path = Dir + "/" + Filename; |
2191 | 1 | int Line = DI->getLine(); |
2192 | | |
2193 | 1 | File.open(Path, std::ios::in); |
2194 | 1 | if (!File.good()) { |
2195 | 0 | errs() << "error opening file: " << Path << "\n"; |
2196 | 0 | return false; |
2197 | 0 | } |
2198 | | |
2199 | 1 | getStrLine(File, Line, Strline); |
2200 | 1 | Trace.append("\n" + Filename + "\n"); |
2201 | 1 | Trace.append(Strline); |
2202 | 1 | Trace.append(" l." + std::to_string(Line) + "\n"); |
2203 | 1 | } |
2204 | | |
2205 | 2 | getStrLine(File, DLs[I].line, Strline); |
2206 | 2 | Trace.append("...\n" + Strline + " l." + std::to_string(DLs[I].line) + |
2207 | 2 | "\n"); |
2208 | 2 | } |
2209 | | |
2210 | 1 | File.close(); |
2211 | | |
2212 | 1 | return true; |
2213 | 1 | } |
2214 | | |
2215 | 50.2k | void DepGraphDCF::floodFunction(Function const *F) { |
2216 | 50.2k | std::queue<MSSAVar *> VarToVisit; |
2217 | 50.2k | std::queue<Value const *> ValueToVisit; |
2218 | | |
2219 | | // 1) taint LLVM and SSA sources |
2220 | 50.2k | for (MSSAVar const *S : ssaSources) { |
2221 | 49.9k | if (funcToSSANodesMap.find(F) == funcToSSANodesMap.end()) { |
2222 | 3.49k | continue; |
2223 | 3.49k | } |
2224 | | |
2225 | 46.4k | if (funcToSSANodesMap[F].find(const_cast<MSSAVar *>(S)) != |
2226 | 46.4k | funcToSSANodesMap[F].end()) { |
2227 | 3.48k | taintedSSANodes.insert(S); |
2228 | 3.48k | } |
2229 | 46.4k | } |
2230 | | |
2231 | 50.2k | for (Value const *S : valueSources) { |
2232 | 1.01k | Instruction const *Inst = dyn_cast<Instruction>(S); |
2233 | 1.01k | if (!Inst || Inst->getParent()->getParent() != F) { |
2234 | 785 | continue; |
2235 | 785 | } |
2236 | | |
2237 | 229 | taintedLLVMNodes.insert(S); |
2238 | 229 | } |
2239 | | |
2240 | | // 2) Add tainted variables of the function to the queue. |
2241 | 50.2k | if (funcToSSANodesMap.find(F) != funcToSSANodesMap.end()) { |
2242 | 1.23M | for (MSSAVar *V : funcToSSANodesMap[F]) { |
2243 | 1.23M | if (taintedSSANodes.find(V) != taintedSSANodes.end()) { |
2244 | 76.0k | VarToVisit.push(V); |
2245 | 76.0k | } |
2246 | 1.23M | } |
2247 | 46.7k | } |
2248 | 50.2k | if (funcToLLVMNodesMap.find(F) != funcToLLVMNodesMap.end()) { |
2249 | 1.16M | for (Value const *V : funcToLLVMNodesMap[F]) { |
2250 | 1.16M | if (taintedLLVMNodes.find(V) != taintedLLVMNodes.end()) { |
2251 | 75.1k | ValueToVisit.push(V); |
2252 | 75.1k | } |
2253 | 1.16M | } |
2254 | 18.0k | } |
2255 | | |
2256 | | // 3) flood function |
2257 | 167k | while (!VarToVisit.empty() || !ValueToVisit.empty()) { |
2258 | 117k | if (!VarToVisit.empty()) { |
2259 | 88.5k | MSSAVar *S = VarToVisit.front(); |
2260 | 88.5k | VarToVisit.pop(); |
2261 | | |
2262 | 88.5k | if (taintResetSSANodes.find(S) != taintResetSSANodes.end()) { |
2263 | 884 | continue; |
2264 | 884 | } |
2265 | | |
2266 | 87.6k | if (ssaToSSAChildren.find(S) != ssaToSSAChildren.end()) { |
2267 | 45.6k | for (MSSAVar *D : ssaToSSAChildren[S]) { |
2268 | 45.6k | if (funcToSSANodesMap.find(F) == funcToSSANodesMap.end()) { |
2269 | 0 | continue; |
2270 | 0 | } |
2271 | | |
2272 | 45.6k | if (funcToSSANodesMap[F].find(D) == funcToSSANodesMap[F].end()) { |
2273 | 26.6k | continue; |
2274 | 26.6k | } |
2275 | 19.0k | if (taintedSSANodes.count(D) != 0) { |
2276 | 12.9k | continue; |
2277 | 12.9k | } |
2278 | | |
2279 | 6.08k | taintedSSANodes.insert(D); |
2280 | 6.08k | VarToVisit.push(D); |
2281 | 6.08k | } |
2282 | 36.7k | } |
2283 | | |
2284 | 87.6k | if (ssaToLLVMChildren.find(S) != ssaToLLVMChildren.end()) { |
2285 | 52.7k | for (Value const *D : ssaToLLVMChildren[S]) { |
2286 | 52.7k | if (funcToLLVMNodesMap[F].find(D) == funcToLLVMNodesMap[F].end()) { |
2287 | 0 | continue; |
2288 | 0 | } |
2289 | | |
2290 | 52.7k | if (taintedLLVMNodes.count(D) != 0) { |
2291 | 45.6k | continue; |
2292 | 45.6k | } |
2293 | | |
2294 | 7.06k | taintedLLVMNodes.insert(D); |
2295 | 7.06k | ValueToVisit.push(D); |
2296 | 7.06k | } |
2297 | 21.6k | } |
2298 | 87.6k | } |
2299 | | |
2300 | 116k | if (!ValueToVisit.empty()) { |
2301 | 86.8k | Value const *S = ValueToVisit.front(); |
2302 | 86.8k | ValueToVisit.pop(); |
2303 | | |
2304 | 86.8k | if (llvmToLLVMChildren.find(S) != llvmToLLVMChildren.end()) { |
2305 | 34.3k | for (Value const *D : llvmToLLVMChildren[S]) { |
2306 | 34.3k | if (funcToLLVMNodesMap.find(F) == funcToLLVMNodesMap.end()) { |
2307 | 0 | continue; |
2308 | 0 | } |
2309 | | |
2310 | 34.3k | if (funcToLLVMNodesMap[F].find(D) == funcToLLVMNodesMap[F].end()) { |
2311 | 12 | continue; |
2312 | 12 | } |
2313 | | |
2314 | 34.3k | if (taintedLLVMNodes.count(D) != 0) { |
2315 | 29.7k | continue; |
2316 | 29.7k | } |
2317 | | |
2318 | 4.57k | taintedLLVMNodes.insert(D); |
2319 | 4.57k | ValueToVisit.push(D); |
2320 | 4.57k | } |
2321 | 34.3k | } |
2322 | | |
2323 | 86.8k | if (llvmToSSAChildren.find(S) != llvmToSSAChildren.end()) { |
2324 | 56.8k | for (MSSAVar *D : llvmToSSAChildren[S]) { |
2325 | 56.8k | if (funcToSSANodesMap.find(F) == funcToSSANodesMap.end()) { |
2326 | 0 | continue; |
2327 | 0 | } |
2328 | 56.8k | if (funcToSSANodesMap[F].find(D) == funcToSSANodesMap[F].end()) { |
2329 | 0 | continue; |
2330 | 0 | } |
2331 | | |
2332 | 56.8k | if (taintedSSANodes.count(D) != 0) { |
2333 | 50.3k | continue; |
2334 | 50.3k | } |
2335 | 6.44k | taintedSSANodes.insert(D); |
2336 | 6.44k | VarToVisit.push(D); |
2337 | 6.44k | } |
2338 | 16.9k | } |
2339 | 86.8k | } |
2340 | 116k | } |
2341 | 50.2k | } |
2342 | | |
2343 | | void DepGraphDCF::floodFunctionFromFunction(Function const *To, |
2344 | 48.5k | Function const *From) { |
2345 | 48.5k | if (funcToSSANodesMap.find(From) != funcToSSANodesMap.end()) { |
2346 | 1.14M | for (MSSAVar *S : funcToSSANodesMap[From]) { |
2347 | 1.14M | if (taintedSSANodes.find(S) == taintedSSANodes.end()) { |
2348 | 1.06M | continue; |
2349 | 1.06M | } |
2350 | 78.8k | if (taintResetSSANodes.find(S) != taintResetSSANodes.end()) { |
2351 | 672 | if (ssaToSSAChildren.find(S) != ssaToSSAChildren.end()) { |
2352 | 683 | for (MSSAVar *D : ssaToSSAChildren[S]) { |
2353 | 683 | if (funcToSSANodesMap.find(To) == funcToSSANodesMap.end()) { |
2354 | 217 | continue; |
2355 | 217 | } |
2356 | 466 | if (funcToSSANodesMap[To].find(D) == funcToSSANodesMap[To].end()) { |
2357 | 457 | continue; |
2358 | 457 | } |
2359 | 9 | taintedSSANodes.erase(D); |
2360 | 9 | } |
2361 | 666 | } |
2362 | | |
2363 | 672 | if (ssaToLLVMChildren.find(S) != ssaToLLVMChildren.end()) { |
2364 | 6 | for (Value const *D : ssaToLLVMChildren[S]) { |
2365 | 6 | if (funcToLLVMNodesMap.find(To) == funcToLLVMNodesMap.end()) { |
2366 | 6 | continue; |
2367 | 6 | } |
2368 | | |
2369 | 0 | if (funcToLLVMNodesMap[To].find(D) == |
2370 | 0 | funcToLLVMNodesMap[To].end()) { |
2371 | 0 | continue; |
2372 | 0 | } |
2373 | 0 | taintedLLVMNodes.erase(D); |
2374 | 0 | } |
2375 | 6 | } |
2376 | | |
2377 | 672 | continue; |
2378 | 672 | } |
2379 | | |
2380 | 78.1k | if (ssaToSSAChildren.find(S) != ssaToSSAChildren.end()) { |
2381 | 42.0k | for (MSSAVar *D : ssaToSSAChildren[S]) { |
2382 | 42.0k | if (funcToSSANodesMap.find(To) == funcToSSANodesMap.end()) { |
2383 | 3.67k | continue; |
2384 | 3.67k | } |
2385 | 38.3k | if (funcToSSANodesMap[To].find(D) == funcToSSANodesMap[To].end()) { |
2386 | 26.6k | continue; |
2387 | 26.6k | } |
2388 | 11.6k | taintedSSANodes.insert(D); |
2389 | 11.6k | } |
2390 | 33.4k | } |
2391 | | |
2392 | 78.1k | if (ssaToLLVMChildren.find(S) != ssaToLLVMChildren.end()) { |
2393 | 45.6k | for (Value const *D : ssaToLLVMChildren[S]) { |
2394 | 45.6k | if (funcToLLVMNodesMap.find(To) == funcToLLVMNodesMap.end()) { |
2395 | 45.6k | continue; |
2396 | 45.6k | } |
2397 | | |
2398 | 56 | if (funcToLLVMNodesMap[To].find(D) == funcToLLVMNodesMap[To].end()) { |
2399 | 56 | continue; |
2400 | 56 | } |
2401 | 0 | taintedLLVMNodes.insert(D); |
2402 | 0 | } |
2403 | 18.7k | } |
2404 | 78.1k | } |
2405 | 44.9k | } |
2406 | | |
2407 | 48.5k | if (funcToLLVMNodesMap.find(From) != funcToLLVMNodesMap.end()) { |
2408 | 1.05M | for (Value const *S : funcToLLVMNodesMap[From]) { |
2409 | 1.05M | if (taintedLLVMNodes.find(S) == taintedLLVMNodes.end()) { |
2410 | 982k | continue; |
2411 | 982k | } |
2412 | | |
2413 | 75.2k | if (llvmToSSAChildren.find(S) != llvmToSSAChildren.end()) { |
2414 | 49.5k | for (MSSAVar *D : llvmToSSAChildren[S]) { |
2415 | 49.5k | if (funcToSSANodesMap.find(To) == funcToSSANodesMap.end()) { |
2416 | 7.35k | continue; |
2417 | 7.35k | } |
2418 | 42.1k | if (funcToSSANodesMap[To].find(D) == funcToSSANodesMap[To].end()) { |
2419 | 42.1k | continue; |
2420 | 42.1k | } |
2421 | 0 | taintedSSANodes.insert(D); |
2422 | 0 | } |
2423 | 14.6k | } |
2424 | | |
2425 | 75.2k | if (llvmToLLVMChildren.find(S) != llvmToLLVMChildren.end()) { |
2426 | 29.7k | for (Value const *D : llvmToLLVMChildren[S]) { |
2427 | 29.7k | if (funcToLLVMNodesMap.find(To) == funcToLLVMNodesMap.end()) { |
2428 | 29.6k | continue; |
2429 | 29.6k | } |
2430 | 87 | if (funcToLLVMNodesMap[To].find(D) == funcToLLVMNodesMap[To].end()) { |
2431 | 85 | continue; |
2432 | 85 | } |
2433 | 2 | taintedLLVMNodes.insert(D); |
2434 | 2 | } |
2435 | 29.7k | } |
2436 | 75.2k | } |
2437 | 16.2k | } |
2438 | 48.5k | } |
2439 | | |
2440 | 16.2k | void DepGraphDCF::resetFunctionTaint(Function const *F) { |
2441 | 16.2k | assert(F && CG.isReachableFromEntry(*F)); |
2442 | 16.2k | if (funcToSSANodesMap.find(F) != funcToSSANodesMap.end()) { |
2443 | 123k | for (MSSAVar *V : funcToSSANodesMap[F]) { |
2444 | 123k | if (taintedSSANodes.find(V) != taintedSSANodes.end()) { |
2445 | 10.2k | taintedSSANodes.erase(V); |
2446 | 10.2k | } |
2447 | 123k | } |
2448 | 14.4k | } |
2449 | | |
2450 | 16.2k | if (funcToLLVMNodesMap.find(F) != funcToLLVMNodesMap.end()) { |
2451 | 742 | for (Value const *V : funcToLLVMNodesMap[F]) { |
2452 | 742 | if (funcToLLVMNodesMap.find(F) != funcToLLVMNodesMap.end()) { |
2453 | 742 | taintedLLVMNodes.erase(V); |
2454 | 742 | } |
2455 | 742 | } |
2456 | 56 | } |
2457 | 16.2k | } |
2458 | | |
2459 | 50.2k | void DepGraphDCF::computeFunctionCSTaintedConds(llvm::Function const *F) { |
2460 | 156k | for (BasicBlock const &BB : *F) { |
2461 | 1.97M | for (Instruction const &I : BB) { |
2462 | 1.97M | if (!isa<CallInst>(I)) { |
2463 | 1.40M | continue; |
2464 | 1.40M | } |
2465 | | |
2466 | 561k | if (callsiteToConds.find(cast<Value>(&I)) != callsiteToConds.end()) { |
2467 | 124k | for (Value const *V : callsiteToConds[cast<Value>(&I)]) { |
2468 | 124k | if (taintedLLVMNodes.find(V) != taintedLLVMNodes.end()) { |
2469 | | // EMMA : if(v->getName() != "cmp1" && v->getName() != "cmp302"){ |
2470 | 73.6k | taintedConditions.insert(V); |
2471 | | // errs() << "EMMA: value tainted: " << v->getName() << "\n"; |
2472 | | //} |
2473 | 73.6k | } |
2474 | 124k | } |
2475 | 116k | } |
2476 | 561k | } |
2477 | 156k | } |
2478 | 50.2k | } |
2479 | | |
2480 | 1.75k | void DepGraphDCF::computeTaintedValuesContextSensitive() { |
2481 | | #ifndef NDEBUG |
2482 | | unsigned FuncToLlvmNodesMapSize = funcToLLVMNodesMap.size(); |
2483 | | unsigned FuncToSsaNodesMapSize = funcToSSANodesMap.size(); |
2484 | | unsigned VarArgNodeSize = varArgNodes.size(); |
2485 | | unsigned LlvmToLlvmChildrenSize = llvmToLLVMChildren.size(); |
2486 | | unsigned LlvmToLlvmParentsSize = llvmToLLVMParents.size(); |
2487 | | unsigned LlvmToSsaChildrenSize = llvmToSSAChildren.size(); |
2488 | | unsigned LlvmToSsaParentsSize = llvmToSSAParents.size(); |
2489 | | unsigned SsaToLlvmChildrenSize = ssaToLLVMChildren.size(); |
2490 | | unsigned SsaToLlvmParentsSize = ssaToLLVMParents.size(); |
2491 | | unsigned SsaToSsaChildrenSize = ssaToSSAChildren.size(); |
2492 | | unsigned SsaToSsaParentsSize = ssaToSSAParents.size(); |
2493 | | unsigned FuncToCallNodesSize = funcToCallNodes.size(); |
2494 | | unsigned CallToFuncEdgesSize = callToFuncEdges.size(); |
2495 | | unsigned CondToCallEdgesSize = condToCallEdges.size(); |
2496 | | unsigned FuncToCallSitesSize = funcToCallSites.size(); |
2497 | | unsigned CallsiteToCondsSize = callsiteToConds.size(); |
2498 | | #endif |
2499 | | |
2500 | 1.75k | PTACallGraphNode const *Entry = CG.getEntry(); |
2501 | 1.75k | if (Entry->getFunction()) { |
2502 | 1.75k | computeTaintedValuesCSForEntry(Entry); |
2503 | 1.75k | } else { |
2504 | 12 | for (auto I = Entry->begin(), E = Entry->end(); I != E; ++I) { |
2505 | 7 | PTACallGraphNode *CalleeNode = I->second; |
2506 | 7 | computeTaintedValuesCSForEntry(CalleeNode); |
2507 | 7 | } |
2508 | 5 | } |
2509 | | |
2510 | 1.75k | assert(FuncToLlvmNodesMapSize == funcToLLVMNodesMap.size()); |
2511 | 1.75k | assert(FuncToSsaNodesMapSize == funcToSSANodesMap.size()); |
2512 | 1.75k | assert(VarArgNodeSize == varArgNodes.size()); |
2513 | 1.75k | assert(LlvmToLlvmChildrenSize == llvmToLLVMChildren.size()); |
2514 | 1.75k | assert(LlvmToLlvmParentsSize == llvmToLLVMParents.size()); |
2515 | 1.75k | assert(LlvmToSsaChildrenSize == llvmToSSAChildren.size()); |
2516 | 1.75k | assert(LlvmToSsaParentsSize == llvmToSSAParents.size()); |
2517 | 1.75k | assert(SsaToLlvmChildrenSize == ssaToLLVMChildren.size()); |
2518 | 1.75k | assert(SsaToLlvmParentsSize == ssaToLLVMParents.size()); |
2519 | 1.75k | assert(SsaToSsaChildrenSize == ssaToSSAChildren.size()); |
2520 | 1.75k | assert(SsaToSsaParentsSize == ssaToSSAParents.size()); |
2521 | 1.75k | assert(FuncToCallNodesSize == funcToCallNodes.size()); |
2522 | 1.75k | assert(CallToFuncEdgesSize == callToFuncEdges.size()); |
2523 | 1.75k | assert(CondToCallEdgesSize == condToCallEdges.size()); |
2524 | 1.75k | assert(FuncToCallSitesSize == funcToCallSites.size()); |
2525 | 1.75k | assert(CallsiteToCondsSize == callsiteToConds.size()); |
2526 | 1.75k | } |
2527 | | |
2528 | | void DepGraphDCF::computeTaintedValuesCSForEntry( |
2529 | 1.76k | PTACallGraphNode const *Entry) { |
2530 | 1.76k | std::vector<PTACallGraphNode const *> S; |
2531 | | |
2532 | 1.76k | std::map<PTACallGraphNode const *, std::set<PTACallGraphNode *>> |
2533 | 1.76k | Node2VisitedChildrenMap; |
2534 | 1.76k | S.push_back(Entry); |
2535 | | |
2536 | 1.76k | bool GoingDown = true; |
2537 | 1.76k | Function const *Prev = NULL; |
2538 | | |
2539 | 52.0k | while (!S.empty()) { |
2540 | 50.2k | PTACallGraphNode const *N = S.back(); |
2541 | 50.2k | bool FoundChildren = false; |
2542 | | |
2543 | | // if (N->getFunction()) |
2544 | | // errs() << "current =" << N->getFunction()->getName() << "\n"; |
2545 | | |
2546 | | /* if (goingDown) |
2547 | | errs() << "down\n"; |
2548 | | else |
2549 | | errs() << "up\n"; |
2550 | | */ |
2551 | 50.2k | if (Prev) { |
2552 | 48.5k | if (GoingDown) { |
2553 | | // errs() << "tainting " << N->getFunction()->getName() << " from " |
2554 | | // << prev->getName() << "\n"; |
2555 | 32.3k | floodFunctionFromFunction(N->getFunction(), Prev); |
2556 | | |
2557 | | // errs() << "tainting " << N->getFunction()->getName() << "\n"; |
2558 | 32.3k | floodFunction(N->getFunction()); |
2559 | | |
2560 | | // errs() << "for each call site get PDF+ and save tainted |
2561 | | // conditions\n"; |
2562 | 32.3k | computeFunctionCSTaintedConds(N->getFunction()); |
2563 | 32.3k | } else { |
2564 | | // errs() << "tainting " << N->getFunction()->getName() << " from " |
2565 | | // << prev->getName() << "\n"; |
2566 | 16.2k | floodFunctionFromFunction(N->getFunction(), Prev); |
2567 | | |
2568 | | // errs() << "tainting " << N->getFunction()->getName() << "\n"; |
2569 | 16.2k | floodFunction(N->getFunction()); |
2570 | | |
2571 | | // errs() << "for each call site get PDF+ and save tainted |
2572 | | // conditions\n"; |
2573 | 16.2k | computeFunctionCSTaintedConds(N->getFunction()); |
2574 | | |
2575 | | // errs() << "untainting " << prev->getName() << "\n"; |
2576 | 16.2k | resetFunctionTaint(Prev); |
2577 | 16.2k | } |
2578 | 48.5k | } else { |
2579 | | // errs() << "tainting " << N->getFunction()->getName() << "\n"; |
2580 | 1.76k | floodFunction(N->getFunction()); |
2581 | | |
2582 | 1.76k | LLVM_DEBUG( |
2583 | 1.76k | dbgs() |
2584 | 1.76k | << "for each call site get PDF+ and save tainted conditions\n"); |
2585 | 1.76k | computeFunctionCSTaintedConds(N->getFunction()); |
2586 | 1.76k | } |
2587 | | |
2588 | | // Add first unvisited callee to stack if any |
2589 | 207k | for (auto I = N->begin(), E = N->end(); I != E; ++I) { |
2590 | 173k | PTACallGraphNode *CalleeNode = I->second; |
2591 | 173k | if (Node2VisitedChildrenMap[N].find(CalleeNode) == |
2592 | 173k | Node2VisitedChildrenMap[N].end()) { |
2593 | 32.3k | FoundChildren = true; |
2594 | 32.3k | Node2VisitedChildrenMap[N].insert(CalleeNode); |
2595 | 32.3k | if (CalleeNode->getFunction()) { |
2596 | 16.2k | S.push_back(CalleeNode); |
2597 | 16.2k | break; |
2598 | 16.2k | } |
2599 | 32.3k | } |
2600 | 173k | } |
2601 | | |
2602 | 50.2k | if (!FoundChildren) { |
2603 | 17.9k | S.pop_back(); |
2604 | 17.9k | GoingDown = false; |
2605 | 32.3k | } else { |
2606 | 32.3k | GoingDown = true; |
2607 | 32.3k | } |
2608 | | |
2609 | 50.2k | Prev = N->getFunction(); |
2610 | 50.2k | } |
2611 | 1.76k | } |
2612 | | |
2613 | | AnalysisKey DepGraphDCFAnalysis::Key; |
2614 | | DepGraphDCFAnalysis::Result |
2615 | 1.76k | DepGraphDCFAnalysis::run(Module &M, ModuleAnalysisManager &AM) { |
2616 | 1.76k | TimeTraceScope TTS("DepGraphDCFAnalysis"); |
2617 | 1.76k | auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); |
2618 | 1.76k | auto &MSSA = AM.getResult<MemorySSAAnalysis>(M); |
2619 | 1.76k | auto const &PTACG = AM.getResult<PTACallGraphAnalysis>(M); |
2620 | 1.76k | return std::make_unique<DepGraphDCF>(MSSA.get(), *PTACG, FAM, M, |
2621 | 1.76k | ContextInsensitive_); |
2622 | 1.76k | } |
2623 | | } // namespace parcoach |