From 79c46cffbfa3642b89f85f297a24ed359e1cb7ea Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 18 Apr 2024 19:12:07 +0200 Subject: [PATCH 1/5] Tie the EF semi-ring to the problem + integrate into solver --- .../DataFlow/IfdsIde/IDETabulationProblem.h | 2 ++ .../DataFlow/IfdsIde/Solver/IDESolver.h | 21 ++++++------ include/phasar/Utils/SemiRing.h | 34 +++++++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 include/phasar/Utils/SemiRing.h diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index 4cdc3610f..5d3dc71f6 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -22,6 +22,7 @@ #include "phasar/Utils/JoinLattice.h" #include "phasar/Utils/NullAnalysisPrinter.h" #include "phasar/Utils/Printer.h" +#include "phasar/Utils/SemiRing.h" #include "phasar/Utils/Soundness.h" #include "llvm/ADT/StringRef.h" @@ -62,6 +63,7 @@ template , public EdgeFunctions, public JoinLattice, + public SemiRing, public AllTopFnProvider { public: using ProblemAnalysisDomain = AnalysisDomainTy; diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h index 3274ced1a..9f10b10e2 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h @@ -406,7 +406,7 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "Compose: " << SumEdgFnE << " * " << f << '\n'); WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)), - f.composeWith(SumEdgFnE)); + IDEProblem.extend(f, SumEdgFnE)); } } } else { @@ -498,15 +498,15 @@ class IDESolver << f4); PHASAR_LOG_LEVEL(DEBUG, " (return * calleeSummary * call)"); - EdgeFunction fPrime = - f4.composeWith(fCalleeSummary).composeWith(f5); + EdgeFunction fPrime = IDEProblem.extend( + IDEProblem.extend(f4, fCalleeSummary), f5); PHASAR_LOG_LEVEL(DEBUG, " = " << fPrime); d_t d5_restoredCtx = restoreContextOnReturnedFact(n, d2, d5); // propagte the effects of the entire call PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f); WorkList.emplace_back( PathEdge(d1, RetSiteN, std::move(d5_restoredCtx)), - f.composeWith(fPrime)); + IDEProblem.extend(f, fPrime)); } } } @@ -538,7 +538,7 @@ class IDESolver .push_back(EdgeFnE); } INC_COUNTER("EF Queries", 1, Full); - auto fPrime = f.composeWith(EdgeFnE); + auto fPrime = IDEProblem.extend(f, EdgeFnE); PHASAR_LOG_LEVEL(DEBUG, "Compose: " << EdgeFnE << " * " << f << " = " << fPrime); WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)), @@ -570,7 +570,7 @@ class IDESolver EdgeFunction g = CachedFlowEdgeFunctions.getNormalEdgeFunction(n, d2, nPrime, d3); PHASAR_LOG_LEVEL(DEBUG, "Queried Normal Edge Function: " << g); - EdgeFunction fPrime = f.composeWith(g); + EdgeFunction fPrime = IDEProblem.extend(f, g); if (SolverConfig.emitESG()) { IntermediateEdgeFunctions[std::make_tuple(n, d2, nPrime, d3)] .push_back(g); @@ -950,7 +950,8 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "Compose: " << f5 << " * " << f << " * " << f4); PHASAR_LOG_LEVEL(DEBUG, " (return * function * call)"); - EdgeFunction fPrime = f4.composeWith(f).composeWith(f5); + EdgeFunction fPrime = + IDEProblem.extend(IDEProblem.extend(f4, f), f5); PHASAR_LOG_LEVEL(DEBUG, " = " << fPrime); // for each jump function coming into the call, propagate to // return site using the composed function @@ -965,7 +966,7 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f3); WorkList.emplace_back(PathEdge(std::move(d3), RetSiteC, std::move(d5_restoredCtx)), - f3.composeWith(fPrime)); + IDEProblem.extend(f3, fPrime)); } } } @@ -1004,7 +1005,7 @@ class IDESolver } INC_COUNTER("EF Queries", 1, Full); PHASAR_LOG_LEVEL(DEBUG, "Compose: " << f5 << " * " << f); - propagteUnbalancedReturnFlow(RetSiteC, d5, f.composeWith(f5), + propagteUnbalancedReturnFlow(RetSiteC, d5, IDEProblem.extend(f, f5), Caller); // register for value processing (2nd IDE phase) UnbalancedRetSites.insert(RetSiteC); @@ -1153,7 +1154,7 @@ class IDESolver // was found return AllTop; }(); - EdgeFunction fPrime = JumpFnE.joinWith(f); + EdgeFunction fPrime = IDEProblem.combine(JumpFnE, f); bool NewFunction = fPrime != JumpFnE; IF_LOG_LEVEL_ENABLED(DEBUG, { diff --git a/include/phasar/Utils/SemiRing.h b/include/phasar/Utils/SemiRing.h new file mode 100644 index 000000000..e4999d329 --- /dev/null +++ b/include/phasar/Utils/SemiRing.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * Copyright (c) 2024 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel and others + *****************************************************************************/ + +#ifndef PHASAR_UTILS_SEMIRING_H +#define PHASAR_UTILS_SEMIRING_H + +#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" + +namespace psr { +template class SemiRing { +public: + using l_t = typename AnalysisDomainTy::l_t; + + virtual ~SemiRing() = default; + + virtual EdgeFunction extend(const EdgeFunction &L, + const EdgeFunction &R) { + return L.composeWith(R); + } + + virtual EdgeFunction combine(const EdgeFunction &L, + const EdgeFunction &R) { + return L.joinWith(R); + } +}; +} // namespace psr + +#endif // PHASAR_UTILS_SEMIRING_H From dd68906a44bd8e2a4f5f88ad2fabbd03b7dc0896 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 18 Apr 2024 19:45:08 +0200 Subject: [PATCH 2/5] Incorporate combine and extend into IIA --- .../DataFlow/IfdsIde/EdgeFunctionUtils.h | 36 ++++ .../Problems/IDEInstInteractionAnalysis.h | 170 ++++++++---------- 2 files changed, 108 insertions(+), 98 deletions(-) diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h index de9db609a..7c8a7ebcb 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h @@ -132,6 +132,22 @@ defaultComposeOrNull(EdgeFunctionRef This, return nullptr; } +template +EdgeFunction +defaultComposeOrNull(const EdgeFunction &This, + const EdgeFunction &SecondFunction) noexcept { + if (llvm::isa>(SecondFunction)) { + return This; + } + if (SecondFunction.isConstant() || llvm::isa>(This)) { + return SecondFunction; + } + if (llvm::isa>(This)) { + return This; + } + return nullptr; +} + template struct ConstantEdgeFunction { using l_t = L; using JLattice = JoinLatticeTraits; @@ -409,6 +425,26 @@ EdgeFunction defaultJoinOrNull(EdgeFunctionRef This, return nullptr; } +template +EdgeFunction defaultJoinOrNull(const EdgeFunction &This, + const EdgeFunction &OtherFunction) { + if (llvm::isa>(OtherFunction) || llvm::isa>(This)) { + return OtherFunction; + } + if (llvm::isa>(OtherFunction) || OtherFunction == This || + llvm::isa>(This)) { + return This; + } + if (llvm::isa>(OtherFunction)) { + if constexpr (N > 0) { + return JoinEdgeFunction::create(This, OtherFunction); + } else if constexpr (HasJoinLatticeTraits) { + return AllBottom{}; + } + } + return nullptr; +} + template EdgeFunction EdgeIdentity::join(EdgeFunctionRef This, const EdgeFunction &OtherFunction) { diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index 40d1dff44..fb70d9d96 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -11,6 +11,7 @@ #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IDEINSTINTERACTIONANALYSIS_H #include "phasar/DataFlow/IfdsIde/DefaultEdgeFunctionSingletonCache.h" +#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" #include "phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h" #include "phasar/DataFlow/IfdsIde/FlowFunctions.h" #include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h" @@ -949,59 +950,15 @@ class IDEInstInteractionAnalysisT l_t computeTarget(ByConstRef /* Src */) const { return Replacement; } - static EdgeFunction compose(EdgeFunctionRef This, - const EdgeFunction SecondFunction) { - - if (auto Default = defaultComposeOrNull(This, SecondFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAKillOrReplaceEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(SecondFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data); - return Cache->createEdgeFunction(std::move(Union)); - } - - if (auto *KR = llvm::dyn_cast(SecondFunction)) { - return SecondFunction; - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAKillOrReplaceEF'"); + static EdgeFunction + compose(EdgeFunctionRef /*This*/, + const EdgeFunction /*SecondFunction*/) { + llvm::report_fatal_error("Implemented in 'extend'"); } - static EdgeFunction join(EdgeFunctionRef This, - const EdgeFunction &OtherFunction) { - /// XXX: Here, we underapproximate joins with EdgeIdentity - if (llvm::isa>(OtherFunction)) { - return This; - } - - if (auto Default = defaultJoinOrNull(This, OtherFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAKillOrReplaceEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(OtherFunction)) { - auto ADCache = OtherFunction.template getCacheOrNull(); - assert(ADCache); - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data); - return ADCache->createEdgeFunction(std::move(Union)); - } - if (auto *KR = llvm::dyn_cast(OtherFunction)) { - auto Union = IDEInstInteractionAnalysisT::joinImpl(This->Replacement, - KR->Replacement); - return Cache->createEdgeFunction(std::move(Union)); - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAKillOrReplaceEF'"); + static EdgeFunction join(EdgeFunctionRef /*This*/, + const EdgeFunction & /*OtherFunction*/) { + llvm::report_fatal_error("Implemented in 'combine'"); } bool operator==(const IIAAKillOrReplaceEF &Other) const noexcept { @@ -1044,55 +1001,15 @@ class IDEInstInteractionAnalysisT return IDEInstInteractionAnalysisT::joinImpl(Src, Data); } - static EdgeFunction compose(EdgeFunctionRef This, - const EdgeFunction &SecondFunction) { - if (auto Default = defaultComposeOrNull(This, SecondFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAAddLabelsEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(SecondFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Data, AD->Data); - return Cache->createEdgeFunction(std::move(Union)); - } - if (auto *KR = llvm::dyn_cast(SecondFunction)) { - return SecondFunction; - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAAddLabelsEF'"); + static EdgeFunction + compose(EdgeFunctionRef /*This*/, + const EdgeFunction & /*SecondFunction*/) { + llvm::report_fatal_error("Implemented in 'extend'"); } - static EdgeFunction join(EdgeFunctionRef This, - const EdgeFunction &OtherFunction) { - /// XXX: Here, we underapproximate joins with EdgeIdentity - if (llvm::isa>(OtherFunction)) { - return This; - } - - if (auto Default = defaultJoinOrNull(This, OtherFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAAddLabelsEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(OtherFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Data, AD->Data); - return Cache->createEdgeFunction(std::move(Union)); - } - if (auto *KR = llvm::dyn_cast(OtherFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Data, KR->Replacement); - return Cache->createEdgeFunction(std::move(Union)); - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAAddLabelsEF'"); + static EdgeFunction join(EdgeFunctionRef /*This*/, + const EdgeFunction & /*OtherFunction*/) { + llvm::report_fatal_error("Implemented in 'combine'"); } bool operator==(const IIAAAddLabelsEF &Other) const noexcept { @@ -1112,6 +1029,63 @@ class IDEInstInteractionAnalysisT } }; + const auto &getData(const EdgeFunction &EF) { + if (const auto *AddLabels = llvm::dyn_cast(EF)) { + return AddLabels->Data; + } + if (const auto *KillOrReplace = llvm::dyn_cast(EF)) { + return KillOrReplace->Replacement; + } + llvm::report_fatal_error( + "found unexpected first edge function in 'getData'"); + } + + EdgeFunction extend(const EdgeFunction &FirstFunction, + const EdgeFunction &SecondFunction) override { + if (auto Default = defaultComposeOrNull(FirstFunction, SecondFunction)) { + return Default; + } + + const auto &ThisData = getData(FirstFunction); + + if (auto *AD = llvm::dyn_cast(SecondFunction)) { + auto Union = IDEInstInteractionAnalysisT::joinImpl(ThisData, AD->Data); + return llvm::isa(FirstFunction) + ? IIAAAddLabelsEFCache.createEdgeFunction(std::move(Union)) + : IIAAKillOrReplaceEFCache.createEdgeFunction( + std::move(Union)); + } + + llvm::report_fatal_error( + "found unexpected second edge function in 'extend'"); + } + + EdgeFunction combine(const EdgeFunction &FirstFunction, + const EdgeFunction &OtherFunction) override { + /// XXX: Here, we underapproximate joins with EdgeIdentity + if (llvm::isa>(FirstFunction)) { + return OtherFunction; + } + if (llvm::isa>(OtherFunction)) { + return FirstFunction; + } + + if (auto Default = defaultJoinOrNull(FirstFunction, OtherFunction)) { + return Default; + } + + const auto &ThisData = getData(FirstFunction); + const auto &OtherData = getData(OtherFunction); + auto Union = IDEInstInteractionAnalysisT::joinImpl(ThisData, OtherData); + + if (llvm::isa(FirstFunction)) { + if (llvm::isa(OtherFunction)) { + return IIAAKillOrReplaceEFCache.createEdgeFunction(std::move(Union)); + } + } + return IIAAAddLabelsEFCache.createEdgeFunction(std::move(Union)); + } + // Provide functionalities for printing things and emitting text reports. static void stripBottomResults(std::unordered_map &Res) { From ad25ac4c9608cfc1ba3af151ea9db64220b618e0 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 20 Apr 2024 14:19:32 +0200 Subject: [PATCH 3/5] minor --- .../IfdsIde/Problems/IDEInstInteractionAnalysis.h | 9 ++++----- include/phasar/Utils/BitVectorSet.h | 10 +++++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index fb70d9d96..43060becc 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -1078,10 +1078,9 @@ class IDEInstInteractionAnalysisT const auto &OtherData = getData(OtherFunction); auto Union = IDEInstInteractionAnalysisT::joinImpl(ThisData, OtherData); - if (llvm::isa(FirstFunction)) { - if (llvm::isa(OtherFunction)) { - return IIAAKillOrReplaceEFCache.createEdgeFunction(std::move(Union)); - } + if (llvm::isa(FirstFunction) && + llvm::isa(OtherFunction)) { + return IIAAKillOrReplaceEFCache.createEdgeFunction(std::move(Union)); } return IIAAAddLabelsEFCache.createEdgeFunction(std::move(Union)); } @@ -1147,7 +1146,7 @@ class IDEInstInteractionAnalysisT } if (const auto *H = llvm::dyn_cast(I)) { if (!H->isIndirectCall() && H->getCalledFunction() && - this->ICF->isHeapAllocatingFunction(H->getCalledFunction())) { + psr::isHeapAllocatingFunction(H->getCalledFunction())) { Variables.insert(H); } } diff --git a/include/phasar/Utils/BitVectorSet.h b/include/phasar/Utils/BitVectorSet.h index 418d90e60..4f7176a46 100644 --- a/include/phasar/Utils/BitVectorSet.h +++ b/include/phasar/Utils/BitVectorSet.h @@ -177,11 +177,11 @@ template class BitVectorSet { } [[nodiscard]] BitVectorSet setUnion(const BitVectorSet &Other) const { - size_t MaxSize = std::max(Bits.size(), Other.Bits.size()); - BitVectorSet Res; - Res.Bits.reserve(MaxSize); - Res.Bits = Bits; - Res.Bits |= Other.Bits; + BitVectorSet Res = Bits.size() < Other.Bits.size() ? Other : *this; + const BitVectorSet &Smaller = + Bits.size() < Other.Bits.size() ? *this : Other; + + Res.Bits |= Smaller.Bits; return Res; } From 81dfbbf92fce0801851cdb2d9b4ff14b08cd0fb1 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 5 May 2024 15:36:16 +0200 Subject: [PATCH 4/5] Fix IIA --- include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h | 3 ++- .../DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h index 7c8a7ebcb..bfbc9d233 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h @@ -139,7 +139,8 @@ defaultComposeOrNull(const EdgeFunction &This, if (llvm::isa>(SecondFunction)) { return This; } - if (SecondFunction.isConstant() || llvm::isa>(This)) { + if (SecondFunction.isConstant() || llvm::isa>(This) || + llvm::isa>(This)) { return SecondFunction; } if (llvm::isa>(This)) { diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index 43060becc..b4410d1f9 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -1037,7 +1037,8 @@ class IDEInstInteractionAnalysisT return KillOrReplace->Replacement; } llvm::report_fatal_error( - "found unexpected first edge function in 'getData'"); + "found unexpected first edge function in 'getData': " + + llvm::Twine(to_string(EF))); } EdgeFunction extend(const EdgeFunction &FirstFunction, @@ -1066,7 +1067,8 @@ class IDEInstInteractionAnalysisT if (llvm::isa>(FirstFunction)) { return OtherFunction; } - if (llvm::isa>(OtherFunction)) { + if (llvm::isa>(OtherFunction) && + !llvm::isa>(FirstFunction)) { return FirstFunction; } From c333910e9a3c5007ebb0899be677b1ce45a9efff Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 12 May 2024 15:08:47 +0200 Subject: [PATCH 5/5] apply review comment --- include/phasar/Utils/BitVectorSet.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/phasar/Utils/BitVectorSet.h b/include/phasar/Utils/BitVectorSet.h index 4f7176a46..308245c82 100644 --- a/include/phasar/Utils/BitVectorSet.h +++ b/include/phasar/Utils/BitVectorSet.h @@ -177,9 +177,9 @@ template class BitVectorSet { } [[nodiscard]] BitVectorSet setUnion(const BitVectorSet &Other) const { - BitVectorSet Res = Bits.size() < Other.Bits.size() ? Other : *this; - const BitVectorSet &Smaller = - Bits.size() < Other.Bits.size() ? *this : Other; + const bool ThisSetIsSmaller = Bits.size() < Other.Bits.size(); + BitVectorSet Res = ThisSetIsSmaller ? Other : *this; + const BitVectorSet &Smaller = ThisSetIsSmaller ? *this : Other; Res.Bits |= Smaller.Bits; return Res;