1818#define PHASAR_DATAFLOW_IFDSIDE_SOLVER_IDESOLVER_H
1919
2020#include " phasar/Config/Configuration.h"
21+ #include " phasar/ControlFlow/SparseCFGProvider.h"
2122#include " phasar/DB/ProjectIRDBBase.h"
2223#include " phasar/DataFlow/IfdsIde/EdgeFunction.h"
2324#include " phasar/DataFlow/IfdsIde/EdgeFunctionStats.h"
3536#include " phasar/DataFlow/IfdsIde/SolverResults.h"
3637#include " phasar/Domain/AnalysisDomain.h"
3738#include " phasar/Utils/Average.h"
39+ #include " phasar/Utils/ByRef.h"
3840#include " phasar/Utils/DOTGraph.h"
3941#include " phasar/Utils/JoinLattice.h"
4042#include " phasar/Utils/Logger.h"
43+ #include " phasar/Utils/Macros.h"
44+ #include " phasar/Utils/Nullable.h"
4145#include " phasar/Utils/PAMMMacros.h"
4246#include " phasar/Utils/Table.h"
4347#include " phasar/Utils/Utilities.h"
4448
4549#include " llvm/ADT/DenseSet.h"
4650#include " llvm/ADT/StringRef.h"
51+ #include " llvm/Support/TypeName.h"
4752#include " llvm/Support/raw_ostream.h"
4853
4954#include " nlohmann/json.hpp"
@@ -81,14 +86,24 @@ class IDESolver
8186 using t_t = typename AnalysisDomainTy::t_t ;
8287 using v_t = typename AnalysisDomainTy::v_t ;
8388
89+ template <typename I>
8490 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),
8794 SolverConfig(Problem.getIFDSIDESolverConfig()),
8895 CachedFlowEdgeFunctions(Problem), AllTop(Problem.allTopFunction()),
8996 JumpFn(std::make_shared<JumpFunctions<AnalysisDomainTy, Container>>()),
9097 Seeds(Problem.initialSeeds()) {
9198 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+ }
92107 }
93108
94109 IDESolver (IDETabulationProblem<AnalysisDomainTy, Container> *Problem,
@@ -339,6 +354,15 @@ class IDESolver
339354 }
340355
341356protected:
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+
342366 // / Lines 13-20 of the algorithm; processing a call site in the caller's
343367 // / context.
344368 // /
@@ -382,6 +406,15 @@ class IDESolver
382406
383407 bool HasNoCalleeInformation = true ;
384408
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+
385418 // for each possible callee
386419 for (f_t SCalledProcN : Callees) { // still line 14
387420 // check if a special summary for the called procedure exists
@@ -409,7 +442,9 @@ class IDESolver
409442 " Queried Summary Edge Function: " << SumEdgFnE);
410443 PHASAR_LOG_LEVEL (DEBUG,
411444 " 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)),
413448 IDEProblem.extend (f, SumEdgFnE));
414449 }
415450 }
@@ -508,8 +543,10 @@ class IDESolver
508543 d_t d5_restoredCtx = restoreContextOnReturnedFact (n, d2, d5);
509544 // propagte the effects of the entire call
510545 PHASAR_LOG_LEVEL (DEBUG, " Compose: " << fPrime << " * " << f);
546+
547+ auto DestN = GetNextUse (RetSiteN, d5_restoredCtx);
511548 WorkList.emplace_back (
512- PathEdge (d1, RetSiteN , std::move (d5_restoredCtx)),
549+ PathEdge (d1, DestN , std::move (d5_restoredCtx)),
513550 IDEProblem.extend (f, fPrime ));
514551 }
515552 }
@@ -545,7 +582,8 @@ class IDESolver
545582 auto fPrime = IDEProblem.extend (f, EdgeFnE);
546583 PHASAR_LOG_LEVEL (DEBUG, " Compose: " << EdgeFnE << " * " << f << " = "
547584 << 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)),
549587 std::move (fPrime ));
550588 }
551589 }
@@ -563,6 +601,8 @@ class IDESolver
563601 EdgeFunction<l_t > f = jumpFunction (Edge);
564602 auto [d1, n, d2] = Edge.consume ();
565603
604+ const auto &Fun = ICF->getFunctionOf (n);
605+
566606 for (const auto nPrime : ICF->getSuccsOf (n)) {
567607 FlowFunctionPtrType FlowFunc =
568608 CachedFlowEdgeFunctions.getNormalFlowFunction (n, nPrime);
@@ -575,14 +615,23 @@ class IDESolver
575615 CachedFlowEdgeFunctions.getNormalEdgeFunction (n, d2, nPrime, d3);
576616 PHASAR_LOG_LEVEL (DEBUG, " Queried Normal Edge Function: " << g);
577617 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+
578627 if (SolverConfig.emitESG ()) {
579- IntermediateEdgeFunctions[std::make_tuple (n, d2, nPrime , d3)]
628+ IntermediateEdgeFunctions[std::make_tuple (n, d2, DestN , d3)]
580629 .push_back (g);
581630 }
582631 PHASAR_LOG_LEVEL (DEBUG,
583632 " Compose: " << g << " * " << f << " = " << fPrime );
584633 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)),
586635 std::move (fPrime ));
587636 }
588637 }
@@ -915,6 +964,7 @@ class IDESolver
915964 for (const auto &Entry : Inc) {
916965 // line 22
917966 n_t c = Entry.first ;
967+ auto &&Fun = ICF->getFunctionOf (c);
918968 // for each return site
919969 for (n_t RetSiteC : ICF->getReturnSitesOfCallAt (c)) {
920970 // compute return-flow function
@@ -968,9 +1018,19 @@ class IDESolver
9681018 d_t d3 = ValAndFunc.first ;
9691019 d_t d5_restoredCtx = restoreContextOnReturnedFact (c, d4, d5);
9701020 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 ));
9741034 }
9751035 }
9761036 }
@@ -1809,7 +1869,10 @@ class IDESolver
18091869 IDETabulationProblem<AnalysisDomainTy, Container> &IDEProblem;
18101870 d_t ZeroValue;
18111871 const i_t *ICF;
1872+ const void *SVFG;
18121873 IFDSIDESolverConfig &SolverConfig;
1874+ Nullable<n_t > (*NextUserOrNullCB)(const void *, ByConstRef<f_t >,
1875+ ByConstRef<d_t >, ByConstRef<n_t >) = nullptr ;
18131876
18141877 std::vector<std::pair<PathEdge<n_t , d_t >, EdgeFunction<l_t >>> WorkList;
18151878 std::vector<std::pair<n_t , d_t >> ValuePropWL;
0 commit comments