18
18
#define PHASAR_DATAFLOW_IFDSIDE_SOLVER_IDESOLVER_H
19
19
20
20
#include " phasar/Config/Configuration.h"
21
+ #include " phasar/ControlFlow/SparseCFGProvider.h"
21
22
#include " phasar/DB/ProjectIRDBBase.h"
22
23
#include " phasar/DataFlow/IfdsIde/EdgeFunction.h"
23
24
#include " phasar/DataFlow/IfdsIde/EdgeFunctionStats.h"
35
36
#include " phasar/DataFlow/IfdsIde/SolverResults.h"
36
37
#include " phasar/Domain/AnalysisDomain.h"
37
38
#include " phasar/Utils/Average.h"
39
+ #include " phasar/Utils/ByRef.h"
38
40
#include " phasar/Utils/DOTGraph.h"
39
41
#include " phasar/Utils/JoinLattice.h"
40
42
#include " phasar/Utils/Logger.h"
43
+ #include " phasar/Utils/Macros.h"
44
+ #include " phasar/Utils/Nullable.h"
41
45
#include " phasar/Utils/PAMMMacros.h"
42
46
#include " phasar/Utils/Table.h"
43
47
#include " phasar/Utils/Utilities.h"
44
48
45
49
#include " llvm/ADT/DenseSet.h"
46
50
#include " llvm/ADT/StringRef.h"
51
+ #include " llvm/Support/TypeName.h"
47
52
#include " llvm/Support/raw_ostream.h"
48
53
49
54
#include " nlohmann/json.hpp"
@@ -81,14 +86,24 @@ class IDESolver
81
86
using t_t = typename AnalysisDomainTy::t_t ;
82
87
using v_t = typename AnalysisDomainTy::v_t ;
83
88
89
+ template <typename I>
84
90
IDESolver (IDETabulationProblem<AnalysisDomainTy, Container> &Problem,
85
- const i_t *ICF)
86
- : IDEProblem(Problem), ZeroValue(Problem.getZeroValue()), ICF(ICF),
91
+ const I *ICF)
92
+ : IDEProblem(Problem), ZeroValue(Problem.getZeroValue()),
93
+ ICF (&static_cast <const i_t &>(*ICF)), SVFG(ICF),
87
94
SolverConfig(Problem.getIFDSIDESolverConfig()),
88
95
CachedFlowEdgeFunctions(Problem), AllTop(Problem.allTopFunction()),
89
96
JumpFn(std::make_shared<JumpFunctions<AnalysisDomainTy, Container>>()),
90
97
Seeds(Problem.initialSeeds()) {
91
98
assert (ICF != nullptr );
99
+
100
+ if constexpr (has_getSparseCFG_v<I, d_t >) {
101
+ NextUserOrNullCB = [](const void *SVFG, ByConstRef<f_t > Fun,
102
+ ByConstRef<d_t > d3, ByConstRef<n_t > n) {
103
+ auto &&SCFG = static_cast <const I *>(SVFG)->getSparseCFG (Fun, d3);
104
+ return SCFG.nextUserOrNull (n);
105
+ };
106
+ }
92
107
}
93
108
94
109
IDESolver (IDETabulationProblem<AnalysisDomainTy, Container> *Problem,
@@ -339,6 +354,15 @@ class IDESolver
339
354
}
340
355
341
356
protected:
357
+ Nullable<n_t > getNextUserOrNull (ByConstRef<f_t > Fun, ByConstRef<d_t > d3,
358
+ ByConstRef<n_t > n) {
359
+ if (!NextUserOrNullCB || IDEProblem.isZeroValue (d3)) {
360
+ return {};
361
+ }
362
+
363
+ return NextUserOrNullCB (SVFG, Fun, d3, n);
364
+ }
365
+
342
366
// / Lines 13-20 of the algorithm; processing a call site in the caller's
343
367
// / context.
344
368
// /
@@ -382,6 +406,15 @@ class IDESolver
382
406
383
407
bool HasNoCalleeInformation = true ;
384
408
409
+ auto &&Fun = ICF->getFunctionOf (n);
410
+ auto GetNextUse = [this , &Fun, &n](n_t nPrime, ByConstRef<d_t > d3) {
411
+ if (auto &&NextUser = getNextUserOrNull (Fun, d3, n)) {
412
+ return psr::unwrapNullable (PSR_FWD (NextUser));
413
+ }
414
+
415
+ return nPrime;
416
+ };
417
+
385
418
// for each possible callee
386
419
for (f_t SCalledProcN : Callees) { // still line 14
387
420
// check if a special summary for the called procedure exists
@@ -409,7 +442,9 @@ class IDESolver
409
442
" Queried Summary Edge Function: " << SumEdgFnE);
410
443
PHASAR_LOG_LEVEL (DEBUG,
411
444
" Compose: " << SumEdgFnE << " * " << f << ' \n ' );
412
- WorkList.emplace_back (PathEdge (d1, ReturnSiteN, std::move (d3)),
445
+
446
+ auto DestN = GetNextUse (ReturnSiteN, d3);
447
+ WorkList.emplace_back (PathEdge (d1, DestN, std::move (d3)),
413
448
IDEProblem.extend (f, SumEdgFnE));
414
449
}
415
450
}
@@ -508,8 +543,10 @@ class IDESolver
508
543
d_t d5_restoredCtx = restoreContextOnReturnedFact (n, d2, d5);
509
544
// propagte the effects of the entire call
510
545
PHASAR_LOG_LEVEL (DEBUG, " Compose: " << fPrime << " * " << f);
546
+
547
+ auto DestN = GetNextUse (RetSiteN, d5_restoredCtx);
511
548
WorkList.emplace_back (
512
- PathEdge (d1, RetSiteN , std::move (d5_restoredCtx)),
549
+ PathEdge (d1, DestN , std::move (d5_restoredCtx)),
513
550
IDEProblem.extend (f, fPrime ));
514
551
}
515
552
}
@@ -545,7 +582,8 @@ class IDESolver
545
582
auto fPrime = IDEProblem.extend (f, EdgeFnE);
546
583
PHASAR_LOG_LEVEL (DEBUG, " Compose: " << EdgeFnE << " * " << f << " = "
547
584
<< fPrime );
548
- WorkList.emplace_back (PathEdge (d1, ReturnSiteN, std::move (d3)),
585
+ auto DestN = GetNextUse (ReturnSiteN, d3);
586
+ WorkList.emplace_back (PathEdge (d1, DestN, std::move (d3)),
549
587
std::move (fPrime ));
550
588
}
551
589
}
@@ -563,6 +601,8 @@ class IDESolver
563
601
EdgeFunction<l_t > f = jumpFunction (Edge);
564
602
auto [d1, n, d2] = Edge.consume ();
565
603
604
+ const auto &Fun = ICF->getFunctionOf (n);
605
+
566
606
for (const auto nPrime : ICF->getSuccsOf (n)) {
567
607
FlowFunctionPtrType FlowFunc =
568
608
CachedFlowEdgeFunctions.getNormalFlowFunction (n, nPrime);
@@ -575,14 +615,23 @@ class IDESolver
575
615
CachedFlowEdgeFunctions.getNormalEdgeFunction (n, d2, nPrime, d3);
576
616
PHASAR_LOG_LEVEL (DEBUG, " Queried Normal Edge Function: " << g);
577
617
EdgeFunction<l_t > fPrime = IDEProblem.extend (f, g);
618
+
619
+ auto DestN = [&, &n = n] {
620
+ if (auto &&NextUser = getNextUserOrNull (Fun, d3, n)) {
621
+ return psr::unwrapNullable (PSR_FWD (NextUser));
622
+ }
623
+
624
+ return nPrime;
625
+ }();
626
+
578
627
if (SolverConfig.emitESG ()) {
579
- IntermediateEdgeFunctions[std::make_tuple (n, d2, nPrime , d3)]
628
+ IntermediateEdgeFunctions[std::make_tuple (n, d2, DestN , d3)]
580
629
.push_back (g);
581
630
}
582
631
PHASAR_LOG_LEVEL (DEBUG,
583
632
" Compose: " << g << " * " << f << " = " << fPrime );
584
633
INC_COUNTER (" EF Queries" , 1 , Full);
585
- WorkList.emplace_back (PathEdge (d1, nPrime , std::move (d3)),
634
+ WorkList.emplace_back (PathEdge (d1, DestN , std::move (d3)),
586
635
std::move (fPrime ));
587
636
}
588
637
}
@@ -915,6 +964,7 @@ class IDESolver
915
964
for (const auto &Entry : Inc) {
916
965
// line 22
917
966
n_t c = Entry.first ;
967
+ auto &&Fun = ICF->getFunctionOf (c);
918
968
// for each return site
919
969
for (n_t RetSiteC : ICF->getReturnSitesOfCallAt (c)) {
920
970
// compute return-flow function
@@ -968,9 +1018,19 @@ class IDESolver
968
1018
d_t d3 = ValAndFunc.first ;
969
1019
d_t d5_restoredCtx = restoreContextOnReturnedFact (c, d4, d5);
970
1020
PHASAR_LOG_LEVEL (DEBUG, " Compose: " << fPrime << " * " << f3);
971
- WorkList.emplace_back (PathEdge (std::move (d3), RetSiteC,
972
- std::move (d5_restoredCtx)),
973
- IDEProblem.extend (f3, fPrime ));
1021
+
1022
+ auto DestN = [&] {
1023
+ if (auto &&NextUser =
1024
+ getNextUserOrNull (Fun, d5_restoredCtx, c)) {
1025
+ return psr::unwrapNullable (PSR_FWD (NextUser));
1026
+ }
1027
+
1028
+ return RetSiteC;
1029
+ }();
1030
+
1031
+ WorkList.emplace_back (
1032
+ PathEdge (std::move (d3), DestN, std::move (d5_restoredCtx)),
1033
+ IDEProblem.extend (f3, fPrime ));
974
1034
}
975
1035
}
976
1036
}
@@ -1809,7 +1869,10 @@ class IDESolver
1809
1869
IDETabulationProblem<AnalysisDomainTy, Container> &IDEProblem;
1810
1870
d_t ZeroValue;
1811
1871
const i_t *ICF;
1872
+ const void *SVFG;
1812
1873
IFDSIDESolverConfig &SolverConfig;
1874
+ Nullable<n_t > (*NextUserOrNullCB)(const void *, ByConstRef<f_t >,
1875
+ ByConstRef<d_t >, ByConstRef<n_t >) = nullptr ;
1813
1876
1814
1877
std::vector<std::pair<PathEdge<n_t , d_t >, EdgeFunction<l_t >>> WorkList;
1815
1878
std::vector<std::pair<n_t , d_t >> ValuePropWL;
0 commit comments