Coverage Report

Created: 2023-10-30 17:15

/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