diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cf419c0e3..7e3a85c14e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: cmake -DCMAKE_INSTALL_PREFIX=./INSTALL -P ./build/cmake_install.cmake PHASAR_ROOT_DIR=$(pwd) cd ./examples/how-to - cmake -S . -B build -Dphasar_ROOT="$PHASAR_ROOT_DIR/INSTALL" + cmake -S . -B build -G Ninja -Dphasar_ROOT="$PHASAR_ROOT_DIR/INSTALL" cmake --build ./build --target run_sample_programs - name: Check test coverage and generate HTML report diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunctionStats.h b/include/phasar/DataFlow/IfdsIde/EdgeFunctionStats.h index 448188b48b..14a0cb1451 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunctionStats.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunctionStats.h @@ -10,7 +10,8 @@ #ifndef PHASAR_DATAFLOW_IFDSIDE_EDGEFUNCTIONSTATS_H #define PHASAR_DATAFLOW_IFDSIDE_EDGEFUNCTIONSTATS_H -#include "llvm/ADT/StringRef.h" +#include "phasar/ControlFlow/ICFG.h" + #include "llvm/Support/raw_ostream.h" #include @@ -72,7 +73,7 @@ class EdgeFunctionStats : public detail::EdgeFunctionStatsData { const EdgeFunctionStats &S); private: - template + template friend class IDESolver; constexpr EdgeFunctionStats( diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h index c7dc59e871..bd258d58a1 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h @@ -18,6 +18,7 @@ #define PHASAR_DATAFLOW_IFDSIDE_SOLVER_IDESOLVER_H #include "phasar/Config/Configuration.h" +#include "phasar/ControlFlow/ICFG.h" #include "phasar/ControlFlow/SparseCFGProvider.h" #include "phasar/DB/ProjectIRDBBase.h" #include "phasar/DataFlow/IfdsIde/EdgeFunction.h" @@ -49,7 +50,6 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/TypeName.h" #include "llvm/Support/raw_ostream.h" #include "nlohmann/json.hpp" @@ -61,7 +61,6 @@ #include #include #include -#include #include namespace psr { @@ -70,10 +69,11 @@ namespace psr { /// Sagiv, Horwitz and Reps. To solve the problem, call solve(). Results /// can then be queried by using resultAt() and resultsAt(). template > + typename Container = std::set, + ICFG ICFGTy = typename AnalysisDomainTy::i_t> class IDESolver - : public IDESolverAPIMixin> { - friend IDESolverAPIMixin>; + : public IDESolverAPIMixin> { + friend IDESolverAPIMixin>; public: using ProblemTy = IDETabulationProblem; @@ -82,27 +82,20 @@ class IDESolver using l_t = typename AnalysisDomainTy::l_t; using n_t = typename AnalysisDomainTy::n_t; - using i_t = typename AnalysisDomainTy::i_t; + using i_t = ICFGTy; using d_t = typename AnalysisDomainTy::d_t; using f_t = typename AnalysisDomainTy::f_t; using t_t = typename AnalysisDomainTy::t_t; using v_t = typename AnalysisDomainTy::v_t; - template I> IDESolver(IDETabulationProblem &Problem, - const I *ICF) + const ICFGTy *ICF) : IDEProblem(Problem), ZeroValue(Problem.getZeroValue()), - ICF(&static_cast(*ICF)), SVFG(ICF), + ICF(&assertNotNull(ICF)), SolverConfig(Problem.getIFDSIDESolverConfig()), CachedFlowEdgeFunctions(Problem), AllTop(Problem.allTopFunction()), JumpFn(std::make_shared>()), - Seeds(Problem.initialSeeds()) { - assert(ICF != nullptr); - - if constexpr (has_getSparseCFG_v) { - NextUserOrNullCB = &nextUserOrNullThunk; - } - } + Seeds(Problem.initialSeeds()) {} IDESolver(IDETabulationProblem *Problem, const i_t *ICF) @@ -357,13 +350,19 @@ class IDESolver } protected: - Nullable getNextUserOrNull(ByConstRef Fun, ByConstRef d3, - ByConstRef n) { - if (!NextUserOrNullCB || IDEProblem.isZeroValue(d3)) { + [[nodiscard]] Nullable getNextUserOrNull(ByConstRef Fun, + ByConstRef d3, + ByConstRef n) { + if constexpr (has_getSparseCFG_v) { + if (IDEProblem.isZeroValue(d3)) { + return {}; + } + + auto &&SCFG = ICF->getSparseCFG(Fun, d3); + return SCFG.nextUserOrNull(n); + } else { return {}; } - - return NextUserOrNullCB(SVFG, Fun, d3, n); } /// Lines 13-20 of the algorithm; processing a call site in the caller's @@ -1778,13 +1777,6 @@ class IDESolver } private: - template - static auto nextUserOrNullThunk(const void *SVFG, ByConstRef Fun, - ByConstRef d3, ByConstRef n) { - auto &&SCFG = static_cast(SVFG)->getSparseCFG(Fun, d3); - return SCFG.nextUserOrNull(n); - }; - /// @brief: Allows less-than comparison based on the statement ID. struct StmtLess { const i_t *ICF; @@ -1881,10 +1873,7 @@ class IDESolver IDETabulationProblem &IDEProblem; d_t ZeroValue; const i_t *ICF; - const void *SVFG; IFDSIDESolverConfig &SolverConfig; - Nullable (*NextUserOrNullCB)(const void *, ByConstRef, - ByConstRef, ByConstRef) = nullptr; std::vector, EdgeFunction>> WorkList; std::vector> ValuePropWL; @@ -1924,28 +1913,29 @@ class IDESolver }; template -IDESolver(Problem &, ICF *) +IDESolver(Problem &, const ICF *) -> IDESolver; + typename Problem::container_type, ICF>; template -IDESolver(Problem *, ICF *) +IDESolver(Problem *, const ICF *) -> IDESolver; + typename Problem::container_type, ICF>; template -using IDESolver_P = IDESolver; +using IDESolver_P + [[deprecated("Let C++ deduce the template arguments of IDESolver, or call " + "solveIDEProblem() instead")]] = + IDESolver; template OwningSolverResults -solveIDEProblem( - IDETabulationProblem &Problem, - const std::convertible_to auto - &ICF) { - IDESolver Solver(&Problem, &ICF); +solveIDEProblem(IDETabulationProblem &Problem, + const ICFG auto &ICF) { + IDESolver Solver(&Problem, &ICF); Solver.solve(); return Solver.consumeSolverResults(); } diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolverAPIMixin.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolverAPIMixin.h index b8af90707c..755d6e8684 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolverAPIMixin.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolverAPIMixin.h @@ -422,6 +422,9 @@ template class IDESolverAPIMixin { } private: + friend Derived; + constexpr IDESolverAPIMixin() noexcept = default; + [[nodiscard]] constexpr Derived &self() & noexcept { static_assert(std::is_base_of_v, "Invalid CRTP instantiation"); diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h index 59055acdb3..de9e85be20 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h @@ -37,26 +37,32 @@ namespace psr { /// IFDSIDESolverConfig#setComputeValues(bool) to disable IDE's /// phase 2. template > -class IFDSSolver - : public IDESolver, Container> { + typename Container = std::set, + ICFG ICFGTy = typename AnalysisDomainTy::i_t> +class IFDSSolver : public IDESolver, + Container, ICFGTy> { + using Base = + IDESolver, Container, ICFGTy>; + public: using ProblemTy = IFDSTabulationProblem; using d_t = typename AnalysisDomainTy::d_t; using n_t = typename AnalysisDomainTy::n_t; - using i_t = typename AnalysisDomainTy::i_t; + using i_t = ICFGTy; - template IfdsDomainTy, - std::convertible_to I> + template + requires(std::same_as, + WithBinaryValueDomain>) IFDSSolver(IFDSTabulationProblem &IFDSProblem, - const I *ICF) - : IDESolver>(IFDSProblem, ICF) {} + const ICFGTy *ICF) + : Base(IFDSProblem, ICF) {} - template IfdsDomainTy, - std::convertible_to I> + template + requires(std::same_as, + WithBinaryValueDomain>) IFDSSolver(IFDSTabulationProblem *IFDSProblem, - const I *ICF) - : IDESolver>(IFDSProblem, ICF) {} + const ICFGTy *ICF) + : Base(IFDSProblem, ICF) {} ~IFDSSolver() override = default; @@ -110,26 +116,27 @@ class IFDSSolver }; template -IFDSSolver(Problem &, ICF *) +IFDSSolver(Problem &, const ICF *) -> IFDSSolver; + typename Problem::container_type, ICF>; template -IFDSSolver(Problem *, ICF *) +IFDSSolver(Problem *, const ICF *) -> IFDSSolver; + typename Problem::container_type, ICF>; template -using IFDSSolver_P = IFDSSolver; +using IFDSSolver_P + [[deprecated("Let C++ deduce the template arguments of IFDSSolver, or call " + "solveIFDSProblem() instead")]] = + IFDSSolver; template OwningSolverResults -solveIFDSProblem( - IFDSTabulationProblem &Problem, - const std::convertible_to auto - &ICF) { - IFDSSolver Solver(Problem, &ICF); +solveIFDSProblem(IFDSTabulationProblem &Problem, + const ICFG auto &ICF) { + IFDSSolver Solver(&Problem, &ICF); Solver.solve(); return Solver.consumeSolverResults(); } diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h index bbd370a715..fc79c6e2b0 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h @@ -54,7 +54,8 @@ namespace psr { /// () by Schiebel, Sattler, /// Schubert, Apel, and Bodden. template > + typename StaticSolverConfigTy = DefaultIDESolverConfig, + ICFG ICFGTy = typename ProblemTy::ProblemAnalysisDomain::i_t> class IterativeIDESolver : private SolverStatsSelector, private detail::IterativeIDESolverResults< @@ -68,9 +69,10 @@ class IterativeIDESolver typename StaticSolverConfigTy::template EdgeFunctionPtrType< typename ProblemTy::ProblemAnalysisDomain::l_t>>, public IDESolverAPIMixin< - IterativeIDESolver> { + IterativeIDESolver> { - friend IDESolverAPIMixin>; + friend IDESolverAPIMixin< + IterativeIDESolver>; public: using domain_t = typename ProblemTy::ProblemAnalysisDomain; @@ -81,7 +83,7 @@ class IterativeIDESolver using v_t = typename domain_t::v_t; using l_t = std::conditional_t; - using i_t = typename domain_t::i_t; + using i_t = ICFGTy; using config_t = StaticSolverConfigTy; @@ -124,30 +126,12 @@ class IterativeIDESolver using typename base_t::summaries_t; - static inline constexpr JumpFunctionGCMode EnableJumpFunctionGC = + static constexpr JumpFunctionGCMode EnableJumpFunctionGC = StaticSolverConfigTy::EnableJumpFunctionGC; - static inline ProblemTy &assertNotNull(ProblemTy *Problem) noexcept { - /// Dereferencing a nullptr is UB, so after initializing this->Problem the - /// null-check might be optimized away to the literal 'true'. - /// However, we still want to pass a pointer to the ctor to make clear that - /// the _reference_ of the problem is captured. - assert(Problem && - "IterativeIDESolver: The IDETabulationProblem must not be null!"); - return *Problem; - } - - static inline const i_t &assertNotNull(const i_t *ICFG) noexcept { - /// Dereferencing a nullptr is UB, so after initializing this->ICFG the - /// null-check might be optimized away to the literal 'true'. - /// However, we still want to pass a pointer to the ctor to make clear that - /// the _reference_ of the problem is captured. - assert(ICFG && "IterativeIDESolver: The ICFG must not be null!"); - return *ICFG; - } - public: - IterativeIDESolver(ProblemTy *Problem, const i_t *ICFG) noexcept + IterativeIDESolver(ProblemTy *Problem, const ICFGTy *ICFG, + StaticSolverConfigTy /*Config*/ = {}) noexcept : Problem(assertNotNull(Problem)), ICFG(assertNotNull(ICFG)) {} auto solve() & { @@ -369,8 +353,6 @@ class IterativeIDESolver } void performDataflowFactPropagation() { - // submitInitialSeeds(); - std::atomic_bool Finished = true; do { /// NOTE: Have a separate function on the worklist to process it, to @@ -869,10 +851,6 @@ class IterativeIDESolver auto ExitId = NodeCompressor.getOrInsert(ExitInst); if constexpr (!UseEndSummaryTab) { - // Summaries = JumpFunctions[ExitId].cellVec([FactId](const auto &Kvp) - // { - // return splitId(Kvp.first).first == FactId; - // }); Summaries = JumpFunctions[ExitId].allOf( [](uint64_t Key) { return splitId(Key).first; }, FactId, [](uint64_t Key) { return splitId(Key).second; }); @@ -911,7 +889,7 @@ class IterativeIDESolver for (ByConstRef SP : ICFG.getStartPointsOf(Callee)) { auto SPId = NodeCompressor.getOrInsert(SP); auto &JumpFn = JumpFunctions[SPId]; - // bool HasResults = !JumpFn.empty(); + for (ByConstRef Fact : CalleeFacts) { auto FactId = FactCompressor.getOrInsert(Fact); @@ -929,8 +907,6 @@ class IterativeIDESolver storeResultsAndPropagate(JumpFn, SPId, FactId, FactId, CalleeId, IdEF); - // CallWL.insert(combineIds(FactId, CalleeId)); - auto It = &AllInterPropagationsOwner.emplace_back(InterPropagationJob{ CallEF, SourceFactId, CalleeId, AtInstructionId, FactId}); auto Inserted = @@ -1081,10 +1057,6 @@ class IterativeIDESolver /// map we are iterating over is bad if constexpr (!UseEndSummaryTab) { - // Summaries = JumpFunctions[ExitId].cellVec( - // [SPFactId{SPFactId}](const auto &Kvp) { - // return splitId(Kvp.first).first == SPFactId; - // }); Summaries = JumpFunctions[ExitId].allOf( [](uint64_t Key) { return splitId(Key).first; }, SPFactId, [](uint64_t Key) { return splitId(Key).second; }); @@ -1311,8 +1283,6 @@ class IterativeIDESolver } void cleanupInterJobsFor(unsigned FunId) { - /// XXX: Use std::erase_if when upgrading to C++20 - auto Cells = SourceFactAndFuncToInterJob.cells(); for (auto Iter = Cells.begin(), End = Cells.end(); Iter != End;) { auto It = Iter++; @@ -1361,7 +1331,7 @@ class IterativeIDESolver } ProblemTy &Problem; - const i_t &ICFG; + const ICFGTy &ICFG; Compressor FunCompressor{}; @@ -1403,10 +1373,6 @@ class IterativeIDESolver llvm::OwningArrayRef RefCountPerFunction{}; llvm::BitVector CandidateFunctionsForGC{}; - // FlowFunctionCache FFCache{ - // &MRes}; - // EdgeFunctionCache EFCache{&MRes}; - flow_edge_function_cache_t FECache{Problem}; }; diff --git a/include/phasar/DataFlow/IfdsIde/Solver/PathAwareIDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/PathAwareIDESolver.h index b8c0912152..5caede846d 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/PathAwareIDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/PathAwareIDESolver.h @@ -18,9 +18,11 @@ namespace psr { template > -class PathAwareIDESolver : public IDESolver { - using base_t = IDESolver; + typename Container = std::set, + ICFG ICFGTy = typename AnalysisDomainTy::i_t> +class PathAwareIDESolver + : public IDESolver { + using base_t = IDESolver; public: using domain_t = AnalysisDomainTy; @@ -30,10 +32,10 @@ class PathAwareIDESolver : public IDESolver { using container_type = typename base_t::container_type; explicit PathAwareIDESolver( - IDETabulationProblem &Problem, const i_t *ICF) - : base_t(Problem, ICF), ESG(Problem.getZeroValue()) { + IDETabulationProblem *Problem, const i_t *ICF) + : base_t(Problem, ICF), ESG(Problem->getZeroValue()) { - if (Problem.getIFDSIDESolverConfig().autoAddZero()) { + if (Problem->getIFDSIDESolverConfig().autoAddZero()) { PHASAR_LOG_LEVEL( WARNING, "The PathAwareIDESolver is initialized with the option 'autoAddZero' " @@ -41,6 +43,10 @@ class PathAwareIDESolver : public IDESolver { } } + explicit PathAwareIDESolver( + IDETabulationProblem &Problem, const i_t *ICF) + : PathAwareIDESolver(&Problem, ICF) {} + [[nodiscard]] const ExplodedSuperGraph & getExplicitESG() const & noexcept { return ESG; @@ -60,9 +66,15 @@ class PathAwareIDESolver : public IDESolver { ExplodedSuperGraph ESG; }; -template -PathAwareIDESolver(ProblemTy &) - -> PathAwareIDESolver; +template +PathAwareIDESolver(ProblemTy &, const ICFGTy *) + -> PathAwareIDESolver; + +template +PathAwareIDESolver(ProblemTy *, const ICFGTy *) + -> PathAwareIDESolver; } // namespace psr diff --git a/include/phasar/DataFlow/IfdsIde/Solver/StaticIDESolverConfig.h b/include/phasar/DataFlow/IfdsIde/Solver/StaticIDESolverConfig.h index 4cf452be2c..e4fe5b6ca5 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/StaticIDESolverConfig.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/StaticIDESolverConfig.h @@ -25,13 +25,13 @@ enum class JumpFunctionGCMode { struct IDESolverConfigBase { template - static inline constexpr bool IsSimple1d = + static constexpr bool IsSimple1d = sizeof(std::pair) <= 32 && std::is_nothrow_move_constructible_v && std::is_nothrow_move_constructible_v && has_llvm_dense_map_info; template - static inline constexpr bool IsSimpleVal = + static constexpr bool IsSimpleVal = sizeof(T) <= 32 && std::is_nothrow_move_constructible_v && has_llvm_dense_map_info; @@ -51,23 +51,31 @@ struct IDESolverConfigBase { template using EdgeFunctionPtrType = EdgeFunction; - static inline constexpr bool AutoAddZero = true; - static inline constexpr bool EnableStatistics = false; - static inline constexpr JumpFunctionGCMode EnableJumpFunctionGC = + static constexpr bool AutoAddZero = true; + static constexpr bool EnableStatistics = false; + static constexpr JumpFunctionGCMode EnableJumpFunctionGC = JumpFunctionGCMode::Disabled; - static inline constexpr bool UseEndSummaryTab = false; + static constexpr bool UseEndSummaryTab = true; }; +template struct WithComputeValues; +using IDESolverConfig = WithComputeValues; +using IFDSSolverConfig = WithComputeValues; + template -struct WithComputeValues : Base { +struct [[clang::preferred_name(IDESolverConfig), + clang::preferred_name(IFDSSolverConfig)]] +WithComputeValues : Base { static constexpr bool ComputeValues = ComputeValuesVal; }; -template struct WithGCMode : Base { - static constexpr JumpFunctionGCMode EnableJumpFunctionGC = GCMode; -}; +template struct WithStats; +using IDESolverConfigWithStats = WithStats; +using IFDSSolverConfigWithStats = WithStats; -template struct WithStats : Base { +template +struct [[clang::preferred_name(IDESolverConfigWithStats), + clang::preferred_name(IFDSSolverConfigWithStats)]] WithStats : Base { static constexpr bool EnableStatistics = EnableStats; }; @@ -77,15 +85,18 @@ struct WithWorkList : Base { }; template struct WithEndSummaryTab : Base { - static inline constexpr bool UseEndSummaryTab = UseEST; + static constexpr bool UseEndSummaryTab = UseEST; }; -using IDESolverConfig = WithComputeValues; -using IFDSSolverConfig = WithComputeValues; -using IDESolverConfigWithStats = WithStats; -using IFDSSolverConfigWithStats = WithStats; +template struct WithGCMode; + using IFDSSolverConfigWithStatsAndGC = WithGCMode; +template +struct [[clang::preferred_name(IFDSSolverConfigWithStatsAndGC)]] WithGCMode + : Base { + static constexpr JumpFunctionGCMode EnableJumpFunctionGC = GCMode; +}; template struct DefaultIDESolverConfig : IDESolverConfig {}; diff --git a/tools/phasar-cli/Controller/AnalysisControllerInternal.h b/tools/phasar-cli/Controller/AnalysisControllerInternal.h index 42547dbff5..df935baf84 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerInternal.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternal.h @@ -24,7 +24,7 @@ #include "AnalysisController.h" namespace psr { -template class IDESolver; +template class IDESolver; } // namespace psr namespace psr::controller { @@ -63,8 +63,9 @@ makeTaintConfig(AnalysisController &Data); template static void statsEmitter(llvm::raw_ostream & /*OS*/, const T & /*Solver*/) {} -template -static void statsEmitter(llvm::raw_ostream &OS, const IDESolver &Solver); +template +static void statsEmitter(llvm::raw_ostream &OS, + const IDESolver &Solver); template static void emitRequestedDataFlowResults(AnalysisController &Data, T &Solver) { diff --git a/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h b/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h index 80b9c3ef82..c986ccc01a 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h @@ -19,19 +19,16 @@ namespace psr::controller { -template -static void statsEmitter(llvm::raw_ostream &OS, const IDESolver &Solver) { +template +static void statsEmitter(llvm::raw_ostream &OS, + const IDESolver &Solver) { OS << "\nEdgeFunction Statistics:\n"; Solver.printEdgeFunctionStatistics(OS); } -template -static void executeIfdsIdeAnalysisImpl(AnalysisController &Data, - const ICFGTy &ICF, ArgTys &&...Args) { - auto Problem = - createAnalysisProblem(*Data.HA, std::forward(Args)...); - SolverTy Solver(Problem, &ICF); +template +static void executeIfdsIdeAnalysisImpl(SolverTy &Solver, + AnalysisController &Data) { { std::optional MeasureTime; if (Data.EmitterOptions & @@ -46,45 +43,56 @@ static void executeIfdsIdeAnalysisImpl(AnalysisController &Data, emitRequestedDataFlowResults(Data, Solver); } -template -static void executeIfdsIdeAnalysis(AnalysisController &Data, ArgTys &&...Args) { - executeIfdsIdeAnalysisImpl( - Data, Data.HA->getICFG(), std::forward(Args)...); -} - template static void executeSparseIfdsIdeAnalysis(AnalysisController &Data, ArgTys &&...Args) { - SparseLLVMBasedICFGView SVFG(&Data.HA->getICFG(), Data.HA->getAliasInfo()); executeIfdsIdeAnalysisImpl( Data, SVFG, std::forward(Args)...); } +template +static void executeIFDSAnalysisWithICFG(AnalysisController &Data, + const ICFG auto &ICF, + ArgTys &&...Args) { + auto Problem = + createAnalysisProblem(*Data.HA, std::forward(Args)...); + IFDSSolver Solver(&Problem, &ICF); + executeIfdsIdeAnalysisImpl(Solver, Data); +} +template +static void executeIDEAnalysisWithICFG(AnalysisController &Data, + const ICFG auto &ICF, ArgTys &&...Args) { + auto Problem = + createAnalysisProblem(*Data.HA, std::forward(Args)...); + IDESolver Solver(&Problem, &ICF); + executeIfdsIdeAnalysisImpl(Solver, Data); +} + template static void executeIFDSAnalysis(AnalysisController &Data, ArgTys &&...Args) { - executeIfdsIdeAnalysis, ProblemTy>( - Data, std::forward(Args)...); + executeIFDSAnalysisWithICFG(Data, Data.HA->getICFG(), + PSR_FWD(Args)...); } template static void executeSparseIFDSAnalysis(AnalysisController &Data, ArgTys &&...Args) { - executeSparseIfdsIdeAnalysis, ProblemTy>( - Data, std::forward(Args)...); + SparseLLVMBasedICFGView SVFG(&Data.HA->getICFG(), Data.HA->getAliasInfo()); + executeIFDSAnalysisWithICFG(Data, SVFG, PSR_FWD(Args)...); } template static void executeIDEAnalysis(AnalysisController &Data, ArgTys &&...Args) { - executeIfdsIdeAnalysis, ProblemTy>( - Data, std::forward(Args)...); + executeIDEAnalysisWithICFG(Data, Data.HA->getICFG(), + PSR_FWD(Args)...); } template static void executeSparseIDEAnalysis(AnalysisController &Data, ArgTys &&...Args) { - executeSparseIfdsIdeAnalysis, ProblemTy>( - Data, std::forward(Args)...); + SparseLLVMBasedICFGView SVFG(&Data.HA->getICFG(), Data.HA->getAliasInfo()); + executeIDEAnalysisWithICFG(Data, SVFG, PSR_FWD(Args)...); } } // namespace psr::controller diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/IterativeIDESolverTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/IterativeIDESolverTest.cpp index d09e95d602..5547d4231d 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/IterativeIDESolverTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/IterativeIDESolverTest.cpp @@ -15,6 +15,7 @@ #include "phasar/Utils/Printer.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/Support/TypeName.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -41,15 +42,14 @@ class IterativeIDESolverTest Soundness::Soundy, /*IncludeGlobals*/ true); IDELinearConstantAnalysis Problem(&IRDB, &ICFG, {"main"}); - IterativeIDESolver Solver( - &Problem, &ICFG); + IterativeIDESolver Solver(&Problem, &ICFG, SolverConfigTy{}); auto Start = std::chrono::steady_clock::now(); Solver.solve(); auto End = std::chrono::steady_clock::now(); auto NewTime = End - Start; - llvm::errs() << "IterativeIDESolver Elapsed:\t" << NewTime.count() - << "ns\n"; + llvm::errs() << llvm::getTypeName() << " Elapsed:\t" + << NewTime.count() << "ns\n"; IDESolver OldSolver(&Problem, &ICFG); Start = std::chrono::steady_clock::now(); @@ -89,16 +89,15 @@ class IterativeIDESolverTest Soundness::Soundy, /*IncludeGlobals*/ true); IDELinearConstantAnalysis Problem(&IRDB, &ICFG, {"main"}); - IterativeIDESolver Solver( - &Problem, &ICFG); + IterativeIDESolver Solver(&Problem, &ICFG, SolverConfigTy{}); auto Start = std::chrono::steady_clock::now(); std::atomic_bool Cancel = false; auto _ = Solver.solveWithAsyncCancellation(Cancel); auto End = std::chrono::steady_clock::now(); auto NewTime = End - Start; - llvm::errs() << "IterativeIDESolver Elapsed:\t" << NewTime.count() - << "ns\n"; + llvm::errs() << llvm::getTypeName() << " Elapsed:\t" + << NewTime.count() << "ns\n"; IDESolver OldSolver(&Problem, &ICFG); Start = std::chrono::steady_clock::now(); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 3237404bbf..19c5e24cfa 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -9,6 +9,7 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h" +#include "phasar/DataFlow/IfdsIde/Solver/GenericSolverResults.h" #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" @@ -81,12 +82,11 @@ class IDETaintAnalysisTest : public ::testing::Test { TaintProblem.emitTextReport(Solver.getSolverResults()); - compareResults(TaintProblem, Solver, GroundTruth); + compareResults(TaintProblem, Solver.getSolverResults(), GroundTruth); } void - compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, - IDESolver_P> &Solver, + compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, auto &&SR, const std::map &GroundTruth) { auto GroundTruthEntries = convertTestingLocationSetMapInIR( GroundTruth, *TaintProblem.getProjectIRDB()); @@ -94,8 +94,7 @@ class IDETaintAnalysisTest : public ::testing::Test { std::map> FoundLeaks; - for (const auto &[LeakInst, LeakVals] : - TaintProblem.getAllLeaks(Solver.getSolverResults())) { + for (const auto &[LeakInst, LeakVals] : TaintProblem.getAllLeaks(SR)) { FoundLeaks[LeakInst].insert(LeakVals.begin(), LeakVals.end()); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index 0b4ff582ca..1d7bc8bd13 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -90,10 +90,7 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { * @param groundTruth results to compare against * @param solver provides the results */ - void compareResults( - const GroundTruthMapTy &GroundTruth, - IDESolver_P> - &Solver) { + void compareResults(const GroundTruthMapTy &GroundTruth, auto &Solver) { auto GroundTruthEntries = convertTestingLocationMapMapInIR(GroundTruth, HA->getProjectIRDB()); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp index c56fcd8db0..1af0cd0c0e 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp @@ -8,6 +8,7 @@ *****************************************************************************/ #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" +#include "phasar/DataFlow/IfdsIde/SolverResults.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h" @@ -36,9 +37,10 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { std::optional HA; OpenSSLSecureMemoryDescription Desc{}; std::optional> TSProblem; - std::unique_ptr< - IDESolver_P>> - Llvmtssolver; + std::optional< + OwningSolverResults> + SR; enum OpenSSLSecureMemoryState { TOP = 42, @@ -55,11 +57,7 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { TSProblem = createAnalysisProblem< IDETypeStateAnalysis>(*HA, &Desc, EntryPoints); - Llvmtssolver = std::make_unique< - IDESolver_P>>( - *TSProblem, &HA->getICFG()); - - Llvmtssolver->solve(); + SR = solveIDEProblem(*TSProblem, HA->getICFG()); } /** @@ -75,7 +73,7 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { auto *Inst = HA->getProjectIRDB().getInstruction(InstToGroundTruth.first); auto GT = InstToGroundTruth.second; std::map Results; - for (auto Result : Llvmtssolver->resultsAt(Inst, true)) { + for (auto Result : SR->resultsAt(Inst, true)) { if (GT.find(getMetaDataID(Result.first)) != GT.end()) { Results.insert(std::pair( getMetaDataID(Result.first), int(Result.second))); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index 07c5187024..92a1a891d1 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -56,11 +56,11 @@ class IFDSConstAnalysisTest : public ::testing::Test { } void compareResultsImpl(const std::set &GroundTruth, - IFDSSolver_P &Solver) { + auto &&SR) { std::set AllMutableAllocas; for (const auto *RR : getRetOrResInstructions()) { - std::set Facts = Solver.ifdsResultsAt(RR); + std::set Facts = SR.ifdsResultsAt(RR); for (const auto *Fact : Facts) { if (isAllocaInstOrHeapAllocaFunction(Fact) || (llvm::isa(Fact) && @@ -75,18 +75,18 @@ class IFDSConstAnalysisTest : public ::testing::Test { } void compareResults(const std::set &GroundTruth, - IFDSSolver_P &Solver) { + auto &Solver) { auto GroundTruthEntries = convertTestingLocationSetInIR(GroundTruth, HA->getProjectIRDB()); - compareResultsImpl(GroundTruthEntries, Solver); + compareResultsImpl(GroundTruthEntries, Solver.getSolverResults()); } void compareResults(std::initializer_list GroundTruth, - IFDSSolver_P &Solver) { + auto &Solver) { auto GroundTruthEntries = convertTestingLocationSetInIR(GroundTruth, HA->getProjectIRDB()); - compareResultsImpl(GroundTruthEntries, Solver); + compareResultsImpl(GroundTruthEntries, Solver.getSolverResults()); } }; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp index 3abcd460da..d0b22830c8 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp @@ -1,6 +1,7 @@ #include "phasar/ControlFlow/CallGraphAnalysisType.h" #include "phasar/ControlFlow/SparseCFGProvider.h" #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" +#include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedCFG.h" #include "phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.h" @@ -50,8 +51,8 @@ TEST_P(LinearConstant, SparseResultsEquivalent) { IDELinearConstantAnalysis LCAProblem(&IRDB, &ICF, Entry); IDELinearConstantAnalysis SLCAProblem(&IRDB, &SICF, Entry); - auto DenseResults = IDESolver(LCAProblem, &ICF).solve(); - auto SparseResults = IDESolver(SLCAProblem, &SICF).solve(); + auto DenseResults = IDESolver(&LCAProblem, &ICF).solve(); + auto SparseResults = IDESolver(&SLCAProblem, &SICF).solve(); DenseResults.dumpResults(ICF, llvm::outs() << "DenseResults:"); SparseResults.dumpResults(SICF, llvm::outs() << "SparseResults:"); @@ -102,8 +103,8 @@ TEST_P(DoubleFreeTA, SparseLeaksEquivalent) { IFDSTaintAnalysis TaintProblem(&IRDB, &PT, &Config, Entry); IFDSTaintAnalysis STaintProblem(&IRDB, &PT, &Config, Entry); - auto DenseResults = IDESolver(TaintProblem, &ICF).solve(); - auto SparseResults = IDESolver(STaintProblem, &SICF).solve(); + auto DenseResults = IFDSSolver(&TaintProblem, &ICF).solve(); + auto SparseResults = IFDSSolver(&STaintProblem, &SICF).solve(); for (const auto &[LeakInst, Leaks] : TaintProblem.Leaks) { auto LeakIt = STaintProblem.Leaks.find(LeakInst);