From cbf9da3fd6b96f491fe99549f43d104eb5ef0621 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 2 Jun 2025 21:52:16 +0200 Subject: [PATCH 01/11] Base files --- ...efaultReachableAllocationSitesIDEProblem.h | 128 ++++++++++++++++++ ...aultReachableAllocationSitesIDEProblem.cpp | 44 ++++++ .../IfdsIde/DefaultFlowFunctionTest.cpp | 42 +++++- 3 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h create mode 100644 lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h new file mode 100644 index 0000000000..d61aab3f48 --- /dev/null +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -0,0 +1,128 @@ +#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H +#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H + +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h" +#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" + +// Forward declaration of types for which we only use its pointer or ref type +namespace llvm { +class Value; +class Instruction; +class Function; +} // namespace llvm + +namespace psr { + +namespace detail { +class IDEReachableAllocationSitesDefaultFlowFunctionsImpl + : private IDENoAliasDefaultFlowFunctionsImpl { +public: + using typename IDENoAliasDefaultFlowFunctionsImpl::d_t; + using typename IDENoAliasDefaultFlowFunctionsImpl::f_t; + using typename IDENoAliasDefaultFlowFunctionsImpl::FlowFunctionPtrType; + using typename IDENoAliasDefaultFlowFunctionsImpl::FlowFunctionType; + using typename IDENoAliasDefaultFlowFunctionsImpl::n_t; + + using IDENoAliasDefaultFlowFunctionsImpl::isFunctionModeled; + + [[nodiscard]] FlowFunctionPtrType getNormalFlowFunctionImpl(n_t Curr, + n_t /*Succ*/); + [[nodiscard]] FlowFunctionPtrType getCallFlowFunctionImpl(n_t CallInst, + f_t CalleeFun); + [[nodiscard]] FlowFunctionPtrType getRetFlowFunctionImpl(n_t CallSite, + f_t /*CalleeFun*/, + n_t ExitInst, + n_t /*RetSite*/); + [[nodiscard]] FlowFunctionPtrType + getCallToRetFlowFunctionImpl(n_t CallSite, n_t /*RetSite*/, + llvm::ArrayRef /*Callees*/); +}; +} // namespace detail + +template +class DefaultReachableAllocationSitesIDEProblem + : public IDETabulationProblem, + protected detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl { +public: + using ProblemAnalysisDomain = AnalysisDomainTy; + using d_t = typename AnalysisDomainTy::d_t; + using n_t = typename AnalysisDomainTy::n_t; + using f_t = typename AnalysisDomainTy::f_t; + using t_t = typename AnalysisDomainTy::t_t; + using v_t = typename AnalysisDomainTy::v_t; + using l_t = typename AnalysisDomainTy::l_t; + using i_t = typename AnalysisDomainTy::i_t; + using db_t = typename AnalysisDomainTy::db_t; + + using ConfigurationTy = HasNoConfigurationType; + + using FlowFunctionType = FlowFunction; + using FlowFunctionPtrType = typename FlowFunctionType::FlowFunctionPtrType; + + using container_type = typename FlowFunctionType::container_type; + + explicit DefaultReachableAllocationSitesIDEProblem( + const ProjectIRDBBase *IRDB, std::vector EntryPoints, + std::optional + ZeroValue) noexcept(std::is_nothrow_move_constructible_v) + : IDETabulationProblem(IRDB, std::move(EntryPoints), + std::move(ZeroValue)), + detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl() {} + + [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, + n_t Succ) override { + return getNormalFlowFunctionImpl(Curr, Succ); + } + + [[nodiscard]] FlowFunctionPtrType + getCallFlowFunction(n_t CallInst, f_t CalleeFun) override { + return getCallFlowFunctionImpl(CallInst, CalleeFun); + } + + [[nodiscard]] FlowFunctionPtrType getRetFlowFunction(n_t CallSite, + f_t CalleeFun, + n_t ExitInst, + n_t RetSite) override { + return getRetFlowFunctionImpl(CallSite, CalleeFun, ExitInst, RetSite); + } + + [[nodiscard]] FlowFunctionPtrType + getCallToRetFlowFunction(n_t CallSite, n_t RetSite, + llvm::ArrayRef Callees) override { + return getCallToRetFlowFunctionImpl(CallSite, RetSite, Callees); + } +}; + +class DefaultReachableAllocationSitesIFDSProblem + : public IFDSTabulationProblem, + protected detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl { +public: + using IFDSTabulationProblem::IFDSTabulationProblem; + + [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, + n_t Succ) override { + return getNormalFlowFunctionImpl(Curr, Succ); + } + + [[nodiscard]] FlowFunctionPtrType + getCallFlowFunction(n_t CallInst, f_t CalleeFun) override { + return getCallFlowFunctionImpl(CallInst, CalleeFun); + } + + [[nodiscard]] FlowFunctionPtrType getRetFlowFunction(n_t CallSite, + f_t CalleeFun, + n_t ExitInst, + n_t RetSite) override { + return getRetFlowFunctionImpl(CallSite, CalleeFun, ExitInst, RetSite); + } + + [[nodiscard]] FlowFunctionPtrType + getCallToRetFlowFunction(n_t CallSite, n_t RetSite, + llvm::ArrayRef Callees) override { + return getCallToRetFlowFunctionImpl(CallSite, RetSite, Callees); + } +}; + +} // namespace psr + +#endif diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp new file mode 100644 index 0000000000..71244b0169 --- /dev/null +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -0,0 +1,44 @@ +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h" + +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h" + +#include "llvm/IR/Instructions.h" + +#include + +using namespace psr; + +using FFTemplates = FlowFunctionTemplates< + detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl::d_t, + detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + FlowFunctionType::container_type>; +using container_type = FFTemplates::container_type; + +auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + getNormalFlowFunctionImpl(n_t Curr, n_t Succ) -> FlowFunctionPtrType { + abort(); +} + +auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) + -> FlowFunctionPtrType { + abort(); +} + +static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, + const llvm::Instruction *Context) { + abort(); +} + +auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + getRetFlowFunctionImpl(n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, + n_t /*RetSite*/) -> FlowFunctionPtrType { + abort(); +} + +auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + getCallToRetFlowFunctionImpl(n_t CallSite, n_t RetSite, + llvm::ArrayRef Callees) + -> FlowFunctionPtrType { + abort(); +} diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index 71d12e3129..70d8830f53 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp @@ -24,7 +24,7 @@ namespace { class IDEAliasImpl : public DefaultAliasAwareIFDSProblem { public: IDEAliasImpl(LLVMProjectIRDB *IRDB) - : DefaultAliasAwareIFDSProblem(IRDB, &PT, {}, {}), PT(IRDB){}; + : DefaultAliasAwareIFDSProblem(IRDB, &PT, {}, {}), PT(IRDB) {}; [[nodiscard]] InitialSeeds initialSeeds() override { return {}; @@ -37,7 +37,17 @@ class IDEAliasImpl : public DefaultAliasAwareIFDSProblem { class IDENoAliasImpl : public DefaultNoAliasIFDSProblem { public: IDENoAliasImpl(LLVMProjectIRDB *IRDB) - : DefaultNoAliasIFDSProblem(IRDB, {}, {}){}; + : DefaultNoAliasIFDSProblem(IRDB, {}, {}) {}; + + [[nodiscard]] InitialSeeds initialSeeds() override { + return {}; + }; +}; + +class IDEReachableAllocationSitesImpl : public DefaultNoAliasIFDSProblem { +public: + IDEReachableAllocationSitesImpl(LLVMProjectIRDB *IRDB) + : DefaultNoAliasIFDSProblem(IRDB, {}, {}) {}; [[nodiscard]] InitialSeeds initialSeeds() override { return {}; @@ -62,6 +72,13 @@ getNormalFlowValueSet(const llvm::Instruction *Instr, return NoAliasLLVMValueSet; } +std::set +getNormalFlowValueSet(const llvm::Instruction *Instr, + IDEReachableAllocationSitesImpl &RASImpl, + const llvm::Value *Arg) { + abort(); +} + std::set getCallFlowValueSet(const llvm::Instruction *Instr, IDEAliasImpl &AliasImpl, const llvm::Value *Arg, const llvm::Function *CalleeFunc) { @@ -82,6 +99,13 @@ getCallFlowValueSet(const llvm::Instruction *Instr, IDENoAliasImpl &NoAliasImpl, return NoAliasLLVMValueSet; } +std::set +getCallFlowValueSet(const llvm::Instruction *Instr, + IDEReachableAllocationSitesImpl &RASImpl, + const llvm::Value *Arg, const llvm::Function *CalleeFunc) { + abort(); +} + std::set getRetFlowValueSet(const llvm::Instruction *Instr, IDEAliasImpl &AliasImpl, const llvm::Value *Arg, const llvm::Instruction *ExitInst) { @@ -102,6 +126,13 @@ getRetFlowValueSet(const llvm::Instruction *Instr, IDENoAliasImpl &NoAliasImpl, return NoAliasLLVMValueSet; } +std::set +getRetFlowValueSet(const llvm::Instruction *Instr, + IDEReachableAllocationSitesImpl &RASImpl, + const llvm::Value *Arg, const llvm::Instruction *ExitInst) { + abort(); +} + std::set getCallToRetFlowValueSet(const llvm::Instruction *Instr, IDEAliasImpl &AliasImpl, const llvm::Value *Arg) { @@ -121,6 +152,13 @@ getCallToRetFlowValueSet(const llvm::Instruction *Instr, return NoAliasLLVMValueSet; } +std::set +getCallToRetFlowValueSet(const llvm::Instruction *Instr, + IDEReachableAllocationSitesImpl &RASImpl, + const llvm::Value *Arg) { + abort(); +} + std::string stringifyValueSet(const std::set &Vals) { std::string Ret; llvm::raw_string_ostream ROS(Ret); From 152770105be99b0ce37570eb611a1b55a2a82923 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 2 Jun 2025 23:00:16 +0200 Subject: [PATCH 02/11] Added missing alias elements --- .../IfdsIde/DefaultAliasAwareIDEProblem.h | 2 +- ...efaultReachableAllocationSitesIDEProblem.h | 35 ++++++++++++++----- ...aultReachableAllocationSitesIDEProblem.cpp | 24 ++++++++++++- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h index 9a73977f97..eec11ad6da 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h @@ -48,7 +48,7 @@ class IDEAliasAwareDefaultFlowFunctionsImpl getCallToRetFlowFunctionImpl(n_t CallSite, n_t /*RetSite*/, llvm::ArrayRef /*Callees*/); -private: +protected: LLVMAliasInfoRef AS; }; } // namespace detail diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h index d61aab3f48..fa146f5a9b 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -1,6 +1,7 @@ #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" @@ -15,15 +16,25 @@ namespace psr { namespace detail { class IDEReachableAllocationSitesDefaultFlowFunctionsImpl - : private IDENoAliasDefaultFlowFunctionsImpl { + : private IDEAliasAwareDefaultFlowFunctionsImpl { public: - using typename IDENoAliasDefaultFlowFunctionsImpl::d_t; - using typename IDENoAliasDefaultFlowFunctionsImpl::f_t; - using typename IDENoAliasDefaultFlowFunctionsImpl::FlowFunctionPtrType; - using typename IDENoAliasDefaultFlowFunctionsImpl::FlowFunctionType; - using typename IDENoAliasDefaultFlowFunctionsImpl::n_t; + using typename IDEAliasAwareDefaultFlowFunctionsImpl::d_t; + using typename IDEAliasAwareDefaultFlowFunctionsImpl::f_t; + using typename IDEAliasAwareDefaultFlowFunctionsImpl::FlowFunctionPtrType; + using typename IDEAliasAwareDefaultFlowFunctionsImpl::FlowFunctionType; + using typename IDEAliasAwareDefaultFlowFunctionsImpl::n_t; - using IDENoAliasDefaultFlowFunctionsImpl::isFunctionModeled; + using IDEAliasAwareDefaultFlowFunctionsImpl::isFunctionModeled; + + [[nodiscard]] constexpr LLVMAliasInfoRef getAliasInfo() const noexcept { + return AS; + } + + constexpr IDEReachableAllocationSitesDefaultFlowFunctionsImpl( + LLVMAliasInfoRef AS) noexcept + : IDEAliasAwareDefaultFlowFunctionsImpl(AS) { + assert(AS && "You must provide an alias information handle!"); + } [[nodiscard]] FlowFunctionPtrType getNormalFlowFunctionImpl(n_t Curr, n_t /*Succ*/); @@ -61,13 +72,19 @@ class DefaultReachableAllocationSitesIDEProblem using container_type = typename FlowFunctionType::container_type; + /// Constructs an IDETabulationProblem with the usual arguments + alias + /// information. + /// + /// \note It is useful to use an instance of FilteredAliasSet for the alias + /// information to lower suprious aliases explicit DefaultReachableAllocationSitesIDEProblem( - const ProjectIRDBBase *IRDB, std::vector EntryPoints, + const ProjectIRDBBase *IRDB, LLVMAliasInfoRef AS, + std::vector EntryPoints, std::optional ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IDETabulationProblem(IRDB, std::move(EntryPoints), std::move(ZeroValue)), - detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl() {} + detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl(AS) {} [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index 71244b0169..2902525b84 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -27,7 +27,29 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, const llvm::Instruction *Context) { - abort(); + container_type Tmp = Facts; + for (const auto *Fact : Facts) { + auto Aliases = AS.getReachableAllocationSites(Fact, Context); + for (const auto *Alias : *Aliases) { + if (const auto *Inst = llvm::dyn_cast(Alias)) { + if (Inst->getParent() == Context->getParent() && + Context->comesBefore(Inst)) { + // We will see that inst later + continue; + } + } + + if (const auto *Load = llvm::dyn_cast(Alias)) { + // Handle at least one level of indirection... + const auto *PointerOp = Load->getPointerOperand()->stripPointerCasts(); + Tmp.insert(PointerOp); + } + + Tmp.insert(Alias); + } + } + + Facts = std::move(Tmp); } auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: From bad9eeb53bdd0da1c9072842c9a619f7bd5334c6 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Sun, 8 Jun 2025 23:55:05 +0200 Subject: [PATCH 03/11] tests + normalflow impl --- ...efaultReachableAllocationSitesIDEProblem.h | 13 +- ...aultReachableAllocationSitesIDEProblem.cpp | 143 +++++++++++++- .../IfdsIde/DefaultFlowFunctionTest.cpp | 187 +++++++++++++++++- 3 files changed, 327 insertions(+), 16 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h index fa146f5a9b..96452df10f 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -2,7 +2,6 @@ #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H #include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h" -#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" // Forward declaration of types for which we only use its pointer or ref type @@ -114,7 +113,17 @@ class DefaultReachableAllocationSitesIFDSProblem : public IFDSTabulationProblem, protected detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl { public: - using IFDSTabulationProblem::IFDSTabulationProblem; + /// Constructs an IFDSTabulationProblem with the usual arguments + alias + /// information. + /// + /// \note It is useful to use an instance of FilteredAliasSet for the alias + /// information to lower suprious aliases + explicit DefaultReachableAllocationSitesIFDSProblem( + const ProjectIRDBBase *IRDB, LLVMAliasInfoRef AS, + std::vector EntryPoints, + d_t ZeroValue) noexcept(std::is_nothrow_move_constructible_v) + : IFDSTabulationProblem(IRDB, std::move(EntryPoints), ZeroValue), + detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl(AS) {} [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index 2902525b84..bcf298e1df 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -3,6 +3,8 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Operator.h" +#include "llvm/Support/Casting.h" #include @@ -16,13 +18,127 @@ using container_type = FFTemplates::container_type; auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getNormalFlowFunctionImpl(n_t Curr, n_t Succ) -> FlowFunctionPtrType { - abort(); + + if (const auto *Store = llvm::dyn_cast(Curr)) { + container_type Gen; + + auto AliasSet = + AS.getReachableAllocationSites(Store->getPointerOperand(), Store); + Gen.insert(AliasSet->begin(), AliasSet->end()); + Gen.insert(Store->getValueOperand()); + + return FFTemplates::lambdaFlow( + [Store, Gen{std::move(Gen)}](d_t Source) -> container_type { + if (Store->getPointerOperand() == Source) { + return {}; + } + if (Store->getValueOperand() == Source) { + return Gen; + } + + return {Source}; + }); + } + + if (const auto *Load = llvm::dyn_cast(Curr)) { + container_type Gen; + + auto AliasSet = + AS.getReachableAllocationSites(Load->getPointerOperand(), Load); + Gen.insert(AliasSet->begin(), AliasSet->end()); + // Gen.insert(Load->getValueOperand()); + + return FFTemplates::lambdaFlow( + [Load, Gen{std::move(Gen)}](d_t Source) -> container_type { + if (Load->getPointerOperand() == Source) { + return Gen; + } + + return {Source}; + }); + } + + if (const auto *UnaryOp = llvm::dyn_cast(Curr)) { + container_type Gen; + + auto AliasSet = AS.getReachableAllocationSites(UnaryOp, UnaryOp); + Gen.insert(AliasSet->begin(), AliasSet->end()); + // Gen.insert(UnaryOp->getValueOperand()); + // TODO: this is still the impl from noalias. Use + // getReachableAllocationSites + return FFTemplates::generateFlow(UnaryOp, UnaryOp->getOperand(0)); + } + + if (const auto *BinaryOp = llvm::dyn_cast(Curr)) { + container_type Gen; + + auto AliasSet = AS.getReachableAllocationSites(BinaryOp, BinaryOp); + Gen.insert(AliasSet->begin(), AliasSet->end()); + // Gen.insert(BinaryOp->getValueOperand()); + // TODO: this is still the impl from noalias. Use + // getReachableAllocationSites + return FFTemplates::generateFlowIf(BinaryOp, [BinaryOp](d_t Source) { + return Source == BinaryOp->getOperand(0) || + Source == BinaryOp->getOperand(1); + }); + } + if (const auto *GetElementPtr = llvm::dyn_cast(Curr)) { + container_type Gen; + + auto AliasSet = AS.getReachableAllocationSites( + GetElementPtr->getPointerOperand(), GetElementPtr); + Gen.insert(AliasSet->begin(), AliasSet->end()); + // Gen.insert(GetElementPtr->getValueOperand()); + // TODO: this is still the impl from noalias. Use + // getReachableAllocationSites + return FFTemplates::generateFlow(GetElementPtr, + GetElementPtr->getPointerOperand()); + } + + if (const auto *Return = llvm::dyn_cast(Curr)) { + container_type Gen; + + auto AliasSet = + AS.getReachableAllocationSites(Return->getReturnValue(), Return); + Gen.insert(AliasSet->begin(), AliasSet->end()); + + return FFTemplates::lambdaFlow( + [Return, Gen{std::move(Gen)}](d_t Source) -> container_type { + if (Return->getReturnValue() == Source) { + return Gen; + } + + return {Source}; + }); + } + + if (const auto *FunctionCall = llvm::dyn_cast(Curr)) { + container_type Gen; + + auto AliasSet = AS.getReachableAllocationSites( + FunctionCall->getReturnedArgOperand(), FunctionCall); + Gen.insert(AliasSet->begin(), AliasSet->end()); + + return FFTemplates::lambdaFlow( + [FunctionCall, Gen{std::move(Gen)}](d_t Source) -> container_type { + if (FunctionCall->getReturnedArgOperand() == Source) { + return Gen; + } + + return {Source}; + }); + } + + return this->IDEAliasAwareDefaultFlowFunctionsImpl::getNormalFlowFunctionImpl( + Curr, Succ); } auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) -> FlowFunctionPtrType { - abort(); + // TODO: talk to Fabian about this function. + return this->IDEAliasAwareDefaultFlowFunctionsImpl::getCallFlowFunctionImpl( + CallInst, CalleeFun); } static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, @@ -55,12 +171,31 @@ static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getRetFlowFunctionImpl(n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, n_t /*RetSite*/) -> FlowFunctionPtrType { - abort(); + // TODO: talk to Fabian about this function. + container_type Gen; + + if (const auto *Call = llvm::dyn_cast(CallSite)) { + const auto PostProcessFacts = [AS = AS, Call](container_type &Facts) { + populateWithMayAliases(AS, Facts, Call); + }; + + return mapFactsToCaller( + Call, ExitInst, + [](d_t Param, d_t Source) { + return Param == Source && Param->getType()->isPointerTy(); + }, + {}, {}, true, true, PostProcessFacts); + } + + return FFTemplates::killAllFlows(); } auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getCallToRetFlowFunctionImpl(n_t CallSite, n_t RetSite, llvm::ArrayRef Callees) -> FlowFunctionPtrType { - abort(); + // TODO: talk to Fabian about this function. + return this + ->IDEAliasAwareDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl( + CallSite, RetSite, Callees); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index 70d8830f53..c69dcd1c82 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp @@ -1,6 +1,7 @@ #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h" #include "phasar/PhasarLLVM/Pointer/FilteredLLVMAliasSet.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" @@ -44,14 +45,19 @@ class IDENoAliasImpl : public DefaultNoAliasIFDSProblem { }; }; -class IDEReachableAllocationSitesImpl : public DefaultNoAliasIFDSProblem { +class IDEReachableAllocationSitesImpl + : public DefaultReachableAllocationSitesIFDSProblem { public: IDEReachableAllocationSitesImpl(LLVMProjectIRDB *IRDB) - : DefaultNoAliasIFDSProblem(IRDB, {}, {}) {}; + : DefaultReachableAllocationSitesIFDSProblem(IRDB, &PT, {}, {}), + PT(IRDB) {}; [[nodiscard]] InitialSeeds initialSeeds() override { return {}; }; + +private: + FilteredLLVMAliasSet PT; }; std::set @@ -76,7 +82,9 @@ std::set getNormalFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { - abort(); + const auto RASNormalFlowFunc = RASImpl.getNormalFlowFunction(Instr, nullptr); + const auto RASLLVMValueSet = RASNormalFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; } std::set @@ -103,7 +111,10 @@ std::set getCallFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Function *CalleeFunc) { - abort(); + const auto RASCallFlowFunc = RASImpl.getCallFlowFunction(Instr, CalleeFunc); + std::set RASLLVMValueSet = + RASCallFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; } std::set @@ -130,7 +141,11 @@ std::set getRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Instruction *ExitInst) { - abort(); + const auto RASRetFlowFunc = + RASImpl.getRetFlowFunction(Instr, nullptr, ExitInst, nullptr); + std::set RASLLVMValueSet = + RASRetFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; } std::set @@ -156,7 +171,10 @@ std::set getCallToRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { - abort(); + const auto RASCallToRetFlowFunc = + RASImpl.getCallToRetFlowFunction(Instr, nullptr, {}); + const auto RASLLVMValueSet = RASCallToRetFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; } std::string stringifyValueSet(const std::set &Vals) { @@ -178,6 +196,8 @@ TEST(PureFlow, NormalFlow01) { "pure_flow/normal_flow/normal_flow_01_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); const auto *MainFunc = IRDB.getFunction("main"); // %0 @@ -204,10 +224,14 @@ TEST(PureFlow, NormalFlow01) { getNormalFlowValueSet(Instr8, AliasImpl, PercentZero)); EXPECT_EQ((std::set{PercentZero, Instr1}), getNormalFlowValueSet(Instr8, NoAliasImpl, PercentZero)); + EXPECT_EQ((std::set{PercentZero, Instr1}), + getNormalFlowValueSet(Instr8, RASImpl, PercentZero)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr8, AliasImpl, Instr1)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr8, NoAliasImpl, Instr1)); + EXPECT_EQ(std::set{}, + getNormalFlowValueSet(Instr8, RASImpl, Instr1)); // store ptr %1, ptr %.addr1, align 8 const auto *Instr10 = IRDB.getInstruction(10); @@ -216,10 +240,14 @@ TEST(PureFlow, NormalFlow01) { getNormalFlowValueSet(Instr10, AliasImpl, PercentOne)); EXPECT_EQ((std::set{PercentOne, Instr2}), getNormalFlowValueSet(Instr10, NoAliasImpl, PercentOne)); + EXPECT_EQ((std::set{PercentOne, Instr2}), + getNormalFlowValueSet(Instr10, RASImpl, PercentOne)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr10, AliasImpl, Instr2)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr10, NoAliasImpl, Instr2)); + EXPECT_EQ(std::set{}, + getNormalFlowValueSet(Instr10, RASImpl, Instr2)); // store ptr %One, ptr %OnePtr, align 8, !dbg !225 const auto *Instr17 = IRDB.getInstruction(17); @@ -228,10 +256,14 @@ TEST(PureFlow, NormalFlow01) { getNormalFlowValueSet(Instr17, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr5}), getNormalFlowValueSet(Instr17, NoAliasImpl, Instr3)); + EXPECT_EQ((std::set{Instr3, Instr5}), + getNormalFlowValueSet(Instr17, RASImpl, Instr3)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr17, AliasImpl, Instr5)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr17, NoAliasImpl, Instr5)); + EXPECT_EQ(std::set{}, + getNormalFlowValueSet(Instr17, RASImpl, Instr5)); // store ptr %Two, ptr %TwoAddr, align 8, !dbg !228 const auto *Instr19 = IRDB.getInstruction(19); @@ -240,16 +272,22 @@ TEST(PureFlow, NormalFlow01) { getNormalFlowValueSet(Instr19, AliasImpl, Instr4)); EXPECT_EQ((std::set{Instr4, Instr6}), getNormalFlowValueSet(Instr19, NoAliasImpl, Instr4)); + EXPECT_EQ((std::set{Instr4, Instr6}), + getNormalFlowValueSet(Instr19, RASImpl, Instr4)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr19, AliasImpl, Instr6)); EXPECT_EQ(std::set{}, getNormalFlowValueSet(Instr19, NoAliasImpl, Instr6)); + EXPECT_EQ(std::set{}, + getNormalFlowValueSet(Instr19, RASImpl, Instr6)); // Other arg EXPECT_EQ(std::set{Instr19}, getNormalFlowValueSet(Instr19, AliasImpl, Instr19)); EXPECT_EQ(std::set{Instr19}, getNormalFlowValueSet(Instr19, NoAliasImpl, Instr19)); + EXPECT_EQ(std::set{Instr19}, + getNormalFlowValueSet(Instr19, RASImpl, Instr19)); } TEST(PureFlow, NormalFlow02) { @@ -257,6 +295,8 @@ TEST(PureFlow, NormalFlow02) { "pure_flow/normal_flow/normal_flow_02_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); const auto *MainFunc = IRDB.getFunction("main"); ASSERT_TRUE(MainFunc); @@ -280,10 +320,14 @@ TEST(PureFlow, NormalFlow02) { getNormalFlowValueSet(Instr8, AliasImpl, PercentZero)); EXPECT_EQ((std::set{PercentZero, Instr2}), getNormalFlowValueSet(Instr8, NoAliasImpl, PercentZero)); + EXPECT_EQ((std::set{PercentZero, Instr2}), + getNormalFlowValueSet(Instr8, RASImpl, PercentZero)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr8, AliasImpl, Instr2)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr8, NoAliasImpl, Instr2)); + EXPECT_EQ((std::set{}), + getNormalFlowValueSet(Instr8, RASImpl, Instr2)); // store ptr %1, ptr %.addr1, align 8, !psr.id !231; | ID: 10 const auto *Instr10 = IRDB.getInstruction(10); @@ -292,16 +336,22 @@ TEST(PureFlow, NormalFlow02) { getNormalFlowValueSet(Instr10, AliasImpl, PercentOne)); EXPECT_EQ((std::set{PercentOne, Instr3}), getNormalFlowValueSet(Instr10, NoAliasImpl, PercentOne)); + EXPECT_EQ((std::set{PercentOne, Instr3}), + getNormalFlowValueSet(Instr10, RASImpl, PercentOne)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr10, AliasImpl, Instr3)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr10, NoAliasImpl, Instr3)); + EXPECT_EQ((std::set{}), + getNormalFlowValueSet(Instr10, RASImpl, Instr3)); // Other arg EXPECT_EQ(std::set{Instr10}, getNormalFlowValueSet(Instr10, AliasImpl, Instr10)); EXPECT_EQ(std::set{Instr10}, getNormalFlowValueSet(Instr10, NoAliasImpl, Instr10)); + EXPECT_EQ(std::set{Instr10}, + getNormalFlowValueSet(Instr10, RASImpl, Instr10)); } TEST(PureFlow, NormalFlow03) { @@ -309,6 +359,8 @@ TEST(PureFlow, NormalFlow03) { "pure_flow/normal_flow/normal_flow_03_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // %One = alloca i32, align 4, !psr.id !222; | ID: 3 const auto *Instr3 = IRDB.getInstruction(3); @@ -324,6 +376,8 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr18, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr18}), getNormalFlowValueSet(Instr18, NoAliasImpl, Instr3)); + EXPECT_EQ((std::set{Instr3, Instr18}), + getNormalFlowValueSet(Instr18, RASImpl, Instr3)); // %3 = load i32, ptr %One, align 4, !dbg !251, !psr.id !252; | ID: 21 const auto *Instr21 = IRDB.getInstruction(21); ASSERT_TRUE(Instr21); @@ -331,6 +385,8 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr21, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr21}), getNormalFlowValueSet(Instr21, NoAliasImpl, Instr3)); + EXPECT_EQ((std::set{Instr3, Instr21}), + getNormalFlowValueSet(Instr21, RASImpl, Instr3)); // %tobool = icmp ne i32 %3, 0, !dbg !251, !psr.id !253; | ID: 22 const auto *Instr22 = IRDB.getInstruction(22); @@ -342,6 +398,8 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr23, AliasImpl, Instr22)); EXPECT_EQ((std::set{Instr22, Instr23}), getNormalFlowValueSet(Instr23, NoAliasImpl, Instr22)); + EXPECT_EQ((std::set{Instr22, Instr23}), + getNormalFlowValueSet(Instr23, RASImpl, Instr22)); // %4 = load i32, ptr %One, align 4, !dbg !261, !psr.id !262; | ID: 27 const auto *Instr27 = IRDB.getInstruction(27); @@ -350,6 +408,8 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr27, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr27}), getNormalFlowValueSet(Instr27, NoAliasImpl, Instr3)); + EXPECT_EQ((std::set{Instr3, Instr27}), + getNormalFlowValueSet(Instr27, RASImpl, Instr3)); // %5 = load i32, ptr %One, align 4, !dbg !263, !psr.id !264; | ID: 28 const auto *Instr28 = IRDB.getInstruction(28); @@ -358,6 +418,8 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr28, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr28}), getNormalFlowValueSet(Instr28, NoAliasImpl, Instr3)); + EXPECT_EQ((std::set{Instr3, Instr28}), + getNormalFlowValueSet(Instr28, RASImpl, Instr3)); // %add = add nsw i32 %4, %5, !dbg !265, !psr.id !266; | ID: 29 const auto *Instr29 = IRDB.getInstruction(29); @@ -366,10 +428,14 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr29, AliasImpl, Instr27)); EXPECT_EQ((std::set{Instr27, Instr29}), getNormalFlowValueSet(Instr29, NoAliasImpl, Instr27)); + EXPECT_EQ((std::set{Instr27, Instr29}), + getNormalFlowValueSet(Instr29, RASImpl, Instr27)); EXPECT_EQ((std::set{Instr28, Instr29}), getNormalFlowValueSet(Instr29, AliasImpl, Instr28)); EXPECT_EQ((std::set{Instr28, Instr29}), getNormalFlowValueSet(Instr29, NoAliasImpl, Instr28)); + EXPECT_EQ((std::set{Instr28, Instr29}), + getNormalFlowValueSet(Instr29, RASImpl, Instr28)); // %One2 = getelementptr inbounds %struct.StructOne, ptr %ForGEP, i32 0, i32 // 0, !dbg !282, !psr.id !283; | ID: 37 @@ -379,6 +445,8 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr37, AliasImpl, Instr8)); EXPECT_EQ((std::set{Instr8, Instr37}), getNormalFlowValueSet(Instr37, NoAliasImpl, Instr8)); + EXPECT_EQ((std::set{Instr8, Instr37}), + getNormalFlowValueSet(Instr37, RASImpl, Instr8)); // %6 = load i32, ptr %One2, align 4, !dbg !282, !psr.id !284; | ID: 38 const auto *Instr38 = IRDB.getInstruction(38); @@ -387,6 +455,8 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr38, AliasImpl, Instr37)); EXPECT_EQ((std::set{Instr37, Instr38}), getNormalFlowValueSet(Instr38, NoAliasImpl, Instr37)); + EXPECT_EQ((std::set{Instr37, Instr38}), + getNormalFlowValueSet(Instr38, RASImpl, Instr37)); } TEST(PureFlow, NormalFlow04) { @@ -394,6 +464,8 @@ TEST(PureFlow, NormalFlow04) { "pure_flow/normal_flow/normal_flow_04_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // %Deref1 = alloca i32, align 4, !psr.id !222; | ID: 7 const auto *Instr7 = IRDB.getInstruction(7); @@ -421,10 +493,14 @@ TEST(PureFlow, NormalFlow04) { getNormalFlowValueSet(Instr26, AliasImpl, Instr25)); EXPECT_EQ((std::set{Instr25, Instr7}), getNormalFlowValueSet(Instr26, NoAliasImpl, Instr25)); + EXPECT_EQ((std::set{Instr25, Instr7}), + getNormalFlowValueSet(Instr26, RASImpl, Instr25)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr26, AliasImpl, Instr7)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr26, NoAliasImpl, Instr7)); + EXPECT_EQ((std::set{}), + getNormalFlowValueSet(Instr26, RASImpl, Instr7)); // store i32 %6, ptr %Deref2, align 4, !dbg !262, !psr.id !270; | ID: 31 const auto *Instr31 = IRDB.getInstruction(31); @@ -433,10 +509,14 @@ TEST(PureFlow, NormalFlow04) { getNormalFlowValueSet(Instr31, AliasImpl, Instr30)); EXPECT_EQ((std::set{Instr8, Instr30}), getNormalFlowValueSet(Instr31, NoAliasImpl, Instr30)); + EXPECT_EQ((std::set{Instr8, Instr30}), + getNormalFlowValueSet(Instr31, RASImpl, Instr30)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr31, AliasImpl, Instr8)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr31, NoAliasImpl, Instr8)); + EXPECT_EQ((std::set{}), + getNormalFlowValueSet(Instr31, RASImpl, Instr8)); // store i32 %10, ptr %Deref3, align 4, !dbg !272, !psr.id !282; | ID: 37 const auto *Instr37 = IRDB.getInstruction(37); @@ -445,10 +525,14 @@ TEST(PureFlow, NormalFlow04) { getNormalFlowValueSet(Instr37, AliasImpl, Instr36)); EXPECT_EQ((std::set{Instr9, Instr36}), getNormalFlowValueSet(Instr37, NoAliasImpl, Instr36)); + EXPECT_EQ((std::set{Instr9, Instr36}), + getNormalFlowValueSet(Instr37, RASImpl, Instr36)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr37, AliasImpl, Instr9)); EXPECT_EQ((std::set{}), getNormalFlowValueSet(Instr37, NoAliasImpl, Instr9)); + EXPECT_EQ((std::set{}), + getNormalFlowValueSet(Instr37, RASImpl, Instr9)); } /* @@ -460,6 +544,8 @@ TEST(PureFlow, CallFlow01) { "pure_flow/call_flow/call_flow_01_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // call void @_Z4callii(i32 noundef %2, i32 noundef %3), !dbg !261, !psr.id // !262; | ID: 26 @@ -484,6 +570,12 @@ TEST(PureFlow, CallFlow01) { EXPECT_EQ(std::set{Param1}, getCallFlowValueSet(Instr26, NoAliasImpl, CallSite->getArgOperand(1), FuncForInstr26)); + EXPECT_EQ(std::set{Param0}, + getCallFlowValueSet(Instr26, RASImpl, CallSite->getArgOperand(0), + FuncForInstr26)); + EXPECT_EQ(std::set{Param1}, + getCallFlowValueSet(Instr26, RASImpl, CallSite->getArgOperand(1), + FuncForInstr26)); } else { FAIL(); } @@ -494,6 +586,8 @@ TEST(PureFlow, CallFlow02) { "pure_flow/call_flow/call_flow_02_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // %One = alloca i32, align 4, !psr.id !251; | ID: 17 const auto *Instr17 = IRDB.getInstruction(17); @@ -546,6 +640,9 @@ TEST(PureFlow, CallFlow02) { EXPECT_EQ((std::set{CallFunc->getArg(0)}), getCallFlowValueSet(Instr50, NoAliasImpl, CSCallFunc->getArgOperand(0), CallFunc)); + EXPECT_EQ((std::set{CallFunc->getArg(0)}), + getCallFlowValueSet(Instr50, RASImpl, CSCallFunc->getArgOperand(0), + CallFunc)); EXPECT_EQ((std::set{SecondCallFunc->getArg(0)}), getCallFlowValueSet(Instr54, AliasImpl, @@ -555,6 +652,10 @@ TEST(PureFlow, CallFlow02) { getCallFlowValueSet(Instr54, NoAliasImpl, CSSecondCallFunc->getArgOperand(0), SecondCallFunc)); + EXPECT_EQ((std::set{SecondCallFunc->getArg(0)}), + getCallFlowValueSet(Instr54, RASImpl, + CSSecondCallFunc->getArgOperand(0), + SecondCallFunc)); EXPECT_EQ((std::set{SecondCallFunc->getArg(1)}), getCallFlowValueSet(Instr54, AliasImpl, CSSecondCallFunc->getArgOperand(1), @@ -563,6 +664,10 @@ TEST(PureFlow, CallFlow02) { getCallFlowValueSet(Instr54, NoAliasImpl, CSSecondCallFunc->getArgOperand(1), SecondCallFunc)); + EXPECT_EQ((std::set{SecondCallFunc->getArg(1)}), + getCallFlowValueSet(Instr54, RASImpl, + CSSecondCallFunc->getArgOperand(1), + SecondCallFunc)); EXPECT_EQ((std::set{SecondCallFunc->getArg(2)}), getCallFlowValueSet(Instr54, AliasImpl, CSSecondCallFunc->getArgOperand(2), @@ -571,6 +676,10 @@ TEST(PureFlow, CallFlow02) { getCallFlowValueSet(Instr54, NoAliasImpl, CSSecondCallFunc->getArgOperand(2), SecondCallFunc)); + EXPECT_EQ((std::set{SecondCallFunc->getArg(2)}), + getCallFlowValueSet(Instr54, RASImpl, + CSSecondCallFunc->getArgOperand(2), + SecondCallFunc)); } /* @@ -582,6 +691,8 @@ TEST(PureFlow, RetFlow01) { "pure_flow/ret_flow/ret_flow_01_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // %Two = alloca i32, align 4, !psr.id !251; | ID: 20 const auto *UnusedValue = IRDB.getValueFromId(20); @@ -597,6 +708,8 @@ TEST(PureFlow, RetFlow01) { getRetFlowValueSet(Instr9, AliasImpl, UnusedValue, Instr0)); EXPECT_EQ(std::set{}, getRetFlowValueSet(Instr9, NoAliasImpl, UnusedValue, Instr0)); + EXPECT_EQ(std::set{}, + getRetFlowValueSet(Instr9, RASImpl, UnusedValue, Instr0)); // %call = call noundef i32 @_Z4callii(i32 noundef %2, i32 noundef %3), !dbg // !281, !psr.id !282; | ID: 36 @@ -619,6 +732,12 @@ TEST(PureFlow, RetFlow01) { EXPECT_EQ(std::set{}, getRetFlowValueSet(Instr36, NoAliasImpl, FuncZ4callii->getArg(1), Instr14)); + EXPECT_EQ( + std::set{}, + getRetFlowValueSet(Instr36, RASImpl, FuncZ4callii->getArg(0), Instr14)); + EXPECT_EQ( + std::set{}, + getRetFlowValueSet(Instr36, RASImpl, FuncZ4callii->getArg(1), Instr14)); // negative tests EXPECT_EQ( @@ -627,6 +746,9 @@ TEST(PureFlow, RetFlow01) { EXPECT_EQ( std::set{}, getRetFlowValueSet(Instr9, NoAliasImpl, FuncZ4callii->getArg(1), Instr0)); + EXPECT_EQ( + std::set{}, + getRetFlowValueSet(Instr9, RASImpl, FuncZ4callii->getArg(1), Instr0)); } TEST(PureFlow, RetFlow02) { @@ -634,6 +756,8 @@ TEST(PureFlow, RetFlow02) { "pure_flow/ret_flow/ret_flow_02_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // %Two = alloca i32, align 4, !psr.id !268; | ID: 29 const auto *UnusedValue = IRDB.getValueFromId(29); @@ -649,6 +773,8 @@ TEST(PureFlow, RetFlow02) { getRetFlowValueSet(Instr14, AliasImpl, UnusedValue, Instr0)); EXPECT_EQ(std::set{}, getRetFlowValueSet(Instr14, NoAliasImpl, UnusedValue, Instr0)); + EXPECT_EQ(std::set{}, + getRetFlowValueSet(Instr14, RASImpl, UnusedValue, Instr0)); // %call1 = call noundef i32 @_Z8newThreev(), !dbg !247, !psr.id !248; | ID: // 18 @@ -662,6 +788,8 @@ TEST(PureFlow, RetFlow02) { getRetFlowValueSet(Instr18, AliasImpl, UnusedValue, Instr4)); EXPECT_EQ(std::set{}, getRetFlowValueSet(Instr18, NoAliasImpl, UnusedValue, Instr4)); + EXPECT_EQ(std::set{}, + getRetFlowValueSet(Instr18, RASImpl, UnusedValue, Instr4)); // %call = call noundef i32 @_Z4callii(i32 noundef %2, i32 noundef %3), !dbg // !298, !psr.id !299; | ID: 45 @@ -684,6 +812,12 @@ TEST(PureFlow, RetFlow02) { EXPECT_EQ(std::set{}, getRetFlowValueSet(Instr45, NoAliasImpl, FuncZ4callii->getArg(1), Instr23)); + EXPECT_EQ( + std::set{}, + getRetFlowValueSet(Instr45, RASImpl, FuncZ4callii->getArg(0), Instr23)); + EXPECT_EQ( + std::set{}, + getRetFlowValueSet(Instr45, RASImpl, FuncZ4callii->getArg(1), Instr23)); // negative tests EXPECT_EQ( @@ -692,6 +826,9 @@ TEST(PureFlow, RetFlow02) { EXPECT_EQ(std::set{}, getRetFlowValueSet(Instr14, NoAliasImpl, FuncZ4callii->getArg(1), Instr0)); + EXPECT_EQ( + std::set{}, + getRetFlowValueSet(Instr14, RASImpl, FuncZ4callii->getArg(1), Instr0)); } TEST(PureFlow, RetFlow03) { @@ -699,6 +836,8 @@ TEST(PureFlow, RetFlow03) { "pure_flow/ret_flow/ret_flow_03_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // %ThreeInCall = alloca i32, align 4, !psr.id !254; | ID: 15 const auto *Instr15 = IRDB.getValueFromId(15); @@ -729,15 +868,17 @@ TEST(PureFlow, RetFlow03) { const auto &Got = getRetFlowValueSet( Instruction30, AliasImpl, FunctionZ8newThreePKi->getArg(0), Instruction9); + EXPECT_EQ(std::set{Instr29}, + getRetFlowValueSet(Instruction30, NoAliasImpl, + FunctionZ8newThreePKi->getArg(0), Instruction9)); + EXPECT_EQ(std::set{Instr29}, + getRetFlowValueSet(Instruction30, RASImpl, + FunctionZ8newThreePKi->getArg(0), Instruction9)); EXPECT_EQ((std::set{Instr15, Instr16, Instr29, Instr30}), Got) << stringifyValueSet(Got); - EXPECT_EQ(std::set{Instr29}, - getRetFlowValueSet(Instruction30, NoAliasImpl, - FunctionZ8newThreePKi->getArg(0), Instruction9)); - // ret ptr @GlobalFour, !dbg !240, !psr.id !241; | ID: 10 const auto *Instruction10 = IRDB.getInstruction(10); ASSERT_TRUE(Instruction10); @@ -777,12 +918,18 @@ TEST(PureFlow, RetFlow03) { EXPECT_EQ(std::set{Instr52}, getRetFlowValueSet(Instruction68, NoAliasImpl, FuncZ4callRiPKi->getArg(0), Instruction48)); + EXPECT_EQ(std::set{Instr52}, + getRetFlowValueSet(Instruction68, RASImpl, + FuncZ4callRiPKi->getArg(0), Instruction48)); EXPECT_EQ(std::set{Instr53}, getRetFlowValueSet(Instruction68, AliasImpl, FuncZ4callRiPKi->getArg(1), Instruction48)); EXPECT_EQ(std::set{Instr53}, getRetFlowValueSet(Instruction68, NoAliasImpl, FuncZ4callRiPKi->getArg(1), Instruction48)); + EXPECT_EQ(std::set{Instr53}, + getRetFlowValueSet(Instruction68, RASImpl, + FuncZ4callRiPKi->getArg(1), Instruction48)); } /* @@ -795,6 +942,8 @@ TEST(PureFlow, CallToRetFlow01) { "pure_flow/call_to_ret_flow/call_to_ret_flow_01_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // store i32 0, ptr %Zero, align 4, !dbg !252, !psr.id !254; | ID: 22 const auto *Instr22 = IRDB.getInstruction(22); @@ -812,16 +961,22 @@ TEST(PureFlow, CallToRetFlow01) { getCallToRetFlowValueSet(Instr30, AliasImpl, Instr22)); EXPECT_EQ(std::set{Instr22}, getCallToRetFlowValueSet(Instr30, NoAliasImpl, Instr22)); + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr30, RASImpl, Instr22)); EXPECT_EQ(std::set{Instr24}, getCallToRetFlowValueSet(Instr30, AliasImpl, Instr24)); EXPECT_EQ(std::set{Instr24}, getCallToRetFlowValueSet(Instr30, NoAliasImpl, Instr24)); + EXPECT_EQ(std::set{Instr24}, + getCallToRetFlowValueSet(Instr30, RASImpl, Instr24)); EXPECT_EQ(std::set{Instr30}, getCallToRetFlowValueSet(Instr30, AliasImpl, Instr30)); EXPECT_EQ(std::set{Instr30}, getCallToRetFlowValueSet(Instr30, NoAliasImpl, Instr30)); + EXPECT_EQ(std::set{Instr30}, + getCallToRetFlowValueSet(Instr30, RASImpl, Instr30)); } TEST(PureFlow, CallToRetFlow02) { @@ -830,6 +985,8 @@ TEST(PureFlow, CallToRetFlow02) { "pure_flow/call_to_ret_flow/call_to_ret_flow_02_cpp_dbg.ll"}); IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); // store i32 3, ptr %Three, align 4, !dbg !223, !psr.id !225; | ID: 5 const auto *Instr5 = IRDB.getInstruction(5); @@ -847,11 +1004,15 @@ TEST(PureFlow, CallToRetFlow02) { getCallToRetFlowValueSet(Instr10, AliasImpl, Instr5)); EXPECT_EQ(std::set{Instr5}, getCallToRetFlowValueSet(Instr10, NoAliasImpl, Instr5)); + EXPECT_EQ(std::set{Instr5}, + getCallToRetFlowValueSet(Instr10, RASImpl, Instr5)); EXPECT_EQ(std::set{Instr8}, getCallToRetFlowValueSet(Instr10, AliasImpl, Instr8)); EXPECT_EQ(std::set{Instr8}, getCallToRetFlowValueSet(Instr10, NoAliasImpl, Instr8)); + EXPECT_EQ(std::set{Instr8}, + getCallToRetFlowValueSet(Instr10, RASImpl, Instr8)); // store i32 1, ptr %One, align 4, !dbg !255, !psr.id !257; | ID: 22 const auto *Instr22 = IRDB.getInstruction(22); @@ -869,16 +1030,22 @@ TEST(PureFlow, CallToRetFlow02) { getCallToRetFlowValueSet(Instr27, AliasImpl, Instr22)); EXPECT_EQ(std::set{Instr22}, getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr22)); + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr22)); EXPECT_EQ(std::set{Instr25}, getCallToRetFlowValueSet(Instr27, AliasImpl, Instr25)); EXPECT_EQ(std::set{Instr25}, getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr25)); + EXPECT_EQ(std::set{Instr25}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr25)); EXPECT_EQ(std::set{Instr27}, getCallToRetFlowValueSet(Instr27, AliasImpl, Instr27)); EXPECT_EQ(std::set{Instr27}, getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr27)); + EXPECT_EQ(std::set{Instr27}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr27)); } }; // namespace From 8fdc1cdff773db464f4697277b3f30255ad7e092 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 10 Jun 2025 19:33:50 +0200 Subject: [PATCH 04/11] added RAS tests --- .../reachable_allocation_sites/CMakeLists.txt | 8 + .../reachable_allocation_sites_01.cpp | 10 ++ .../reachable_allocation_sites_02.cpp | 13 ++ .../IfdsIde/DefaultFlowFunctionTest.cpp | 139 ++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt create mode 100644 test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp create mode 100644 test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp diff --git a/test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt b/test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt new file mode 100644 index 0000000000..aba3a439d8 --- /dev/null +++ b/test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt @@ -0,0 +1,8 @@ +set(NoMem2regSources + reachable_allocation_sites_01.cpp + reachable_allocation_sites_02.cpp +) + +foreach(TEST_SRC ${NoMem2regSources}) + generate_ll_file(FILE ${TEST_SRC} DEBUG) +endforeach(TEST_SRC) diff --git a/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp b/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp new file mode 100644 index 0000000000..9a6e0ef087 --- /dev/null +++ b/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp @@ -0,0 +1,10 @@ +int TestInt = 6; + +int *call2() { return &TestInt; } +int *call1() { return call2(); } + +int main(int /*argc*/, char * /*argv*/[]) { + int *CallReturn = call1(); + + return 0; +} diff --git a/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp b/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp new file mode 100644 index 0000000000..a66d480938 --- /dev/null +++ b/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp @@ -0,0 +1,13 @@ +int TestInt = 6; +int TestInt2 = 12; + +int *call4() { return &TestInt2; } +int *call3() { return &TestInt; } +int call2() { return *call3() + *call4(); } +int call1() { return call2(); } + +int main(int /*argc*/, char * /*argv*/[]) { + int CallReturn = call1(); + + return 0; +} diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index c69dcd1c82..22dcddff30 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp @@ -82,9 +82,12 @@ std::set getNormalFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { +#if false const auto RASNormalFlowFunc = RASImpl.getNormalFlowFunction(Instr, nullptr); const auto RASLLVMValueSet = RASNormalFlowFunc->computeTargets(Arg); return RASLLVMValueSet; +#endif + return {}; } std::set @@ -111,10 +114,13 @@ std::set getCallFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Function *CalleeFunc) { +#if false const auto RASCallFlowFunc = RASImpl.getCallFlowFunction(Instr, CalleeFunc); std::set RASLLVMValueSet = RASCallFlowFunc->computeTargets(Arg); return RASLLVMValueSet; +#endif + return {}; } std::set @@ -141,11 +147,14 @@ std::set getRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Instruction *ExitInst) { +#if false const auto RASRetFlowFunc = RASImpl.getRetFlowFunction(Instr, nullptr, ExitInst, nullptr); std::set RASLLVMValueSet = RASRetFlowFunc->computeTargets(Arg); return RASLLVMValueSet; +#endif + return {}; } std::set @@ -171,10 +180,13 @@ std::set getCallToRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { +#if false const auto RASCallToRetFlowFunc = RASImpl.getCallToRetFlowFunction(Instr, nullptr, {}); const auto RASLLVMValueSet = RASCallToRetFlowFunc->computeTargets(Arg); return RASLLVMValueSet; +#endif + return {}; } std::string stringifyValueSet(const std::set &Vals) { @@ -1048,6 +1060,133 @@ TEST(PureFlow, CallToRetFlow02) { getCallToRetFlowValueSet(Instr27, RASImpl, Instr27)); } +TEST(PureFlow, ReachableAllocationSites01) { + LLVMProjectIRDB IRDB({unittest::PathToLLTestFiles + + "pure_flow/reachable_allocation_sites/" + "reachable_allocation_sites_01_cpp_dbg.ll"}); + IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); + IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); +#if false + + // ret ptr @TestInt, !dbg !21, !psr.id !22; | ID: 1 + + // %call = call noundef ptr @_Z5call2v(), !dbg !24, !psr.id !25; | ID: 2 + // ret ptr %call, !dbg !26, !psr.id !27; | ID: 3 + + // %call = call noundef ptr @_Z5call1v(), !dbg !50, !psr.id !51; | ID: 14 + // store ptr %call, ptr %CallReturn, align 8, !dbg !48, !psr.id !52; | ID: 15 + + // + const auto *Instr = IRDB.getInstruction(); + ASSERT_TRUE(Instr); + + // EXPECT_EQ(std::set{Instr5}, + // getCallToRetFlowValueSet(Instr10, AliasImpl, Instr5)); + + // store i32 1, ptr %One, align 4, !dbg !255, !psr.id !257; | ID: 22 + const auto *Instr22 = IRDB.getInstruction(22); + ASSERT_TRUE(Instr22); + + // store i32 2, ptr %Two, align 4, !dbg !261, !psr.id !263; | ID: 25 + const auto *Instr25 = IRDB.getInstruction(25); + ASSERT_TRUE(Instr25); + + // ret i32 0, !dbg !266, !psr.id !267; | ID: 27 + const auto *Instr27 = IRDB.getInstruction(27); + ASSERT_TRUE(Instr27); + + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr27, AliasImpl, Instr22)); + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr22)); + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr22)); + + EXPECT_EQ(std::set{Instr25}, + getCallToRetFlowValueSet(Instr27, AliasImpl, Instr25)); + EXPECT_EQ(std::set{Instr25}, + getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr25)); + EXPECT_EQ(std::set{Instr25}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr25)); + + EXPECT_EQ(std::set{Instr27}, + getCallToRetFlowValueSet(Instr27, AliasImpl, Instr27)); + EXPECT_EQ(std::set{Instr27}, + getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr27)); + EXPECT_EQ(std::set{Instr27}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr27)); +#endif +} + +TEST(PureFlow, ReachableAllocationSites02) { + LLVMProjectIRDB IRDB({unittest::PathToLLTestFiles + + "pure_flow/reachable_allocation_sites/" + "reachable_allocation_sites_02_cpp_dbg.ll"}); + IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); + IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); + IDEReachableAllocationSitesImpl RASImpl = + IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); +#if false + + // ret ptr @TestInt2, !dbg !24, !psr.id !25; | ID: 2 + + // ret ptr @TestInt, !dbg !27, !psr.id !28; | ID: 3 + + // %add = add nsw i32 %0, %1, !dbg !40, !psr.id !41; | ID: 8 + // ret i32 %add, !dbg !42, !psr.id !43; | ID: 9 + + // %call = call noundef i32 @_Z5call2v(), !dbg !45, !psr.id !46; | ID: 10 + // ret i32 %call, !dbg !47, !psr.id !48; | ID: 11 + + // %call = call noundef i32 @_Z5call1v(), !dbg !71, !psr.id !72; | ID: 22 + // store i32 %call, ptr %CallReturn, align 4, !dbg !69, !psr.id !73; | ID: 23 + + // + const auto *Instr = IRDB.getInstruction(); + ASSERT_TRUE(Instr); + + // EXPECT_EQ(std::set{Instr5}, + // getCallToRetFlowValueSet(Instr10, AliasImpl, Instr5)); + + // store i32 1, ptr %One, align 4, !dbg !255, !psr.id !257; | ID: 22 + const auto *Instr22 = IRDB.getInstruction(22); + ASSERT_TRUE(Instr22); + + // store i32 2, ptr %Two, align 4, !dbg !261, !psr.id !263; | ID: 25 + const auto *Instr25 = IRDB.getInstruction(25); + ASSERT_TRUE(Instr25); + + // ret i32 0, !dbg !266, !psr.id !267; | ID: 27 + const auto *Instr27 = IRDB.getInstruction(27); + ASSERT_TRUE(Instr27); + + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr27, AliasImpl, Instr22)); + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr22)); + EXPECT_EQ(std::set{Instr22}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr22)); + + EXPECT_EQ(std::set{Instr25}, + getCallToRetFlowValueSet(Instr27, AliasImpl, Instr25)); + EXPECT_EQ(std::set{Instr25}, + getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr25)); + EXPECT_EQ(std::set{Instr25}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr25)); + + EXPECT_EQ(std::set{Instr27}, + getCallToRetFlowValueSet(Instr27, AliasImpl, Instr27)); + EXPECT_EQ(std::set{Instr27}, + getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr27)); + EXPECT_EQ(std::set{Instr27}, + getCallToRetFlowValueSet(Instr27, RASImpl, Instr27)); +#endif +} + }; // namespace // main function for the test case From 08b8f9e55bfcc46722d801cad809b97e20f97c67 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 11 Jun 2025 20:30:02 +0200 Subject: [PATCH 05/11] WIP reworking flow functions --- ...efaultReachableAllocationSitesIDEProblem.h | 19 ++- ...aultReachableAllocationSitesIDEProblem.cpp | 137 ++++++++---------- .../reachable_allocation_sites/CMakeLists.txt | 8 - .../reachable_allocation_sites_01.cpp | 10 -- .../reachable_allocation_sites_02.cpp | 13 -- .../IfdsIde/DefaultFlowFunctionTest.cpp | 127 ---------------- 6 files changed, 72 insertions(+), 242 deletions(-) delete mode 100644 test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt delete mode 100644 test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp delete mode 100644 test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h index 96452df10f..64948f021b 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -15,15 +15,15 @@ namespace psr { namespace detail { class IDEReachableAllocationSitesDefaultFlowFunctionsImpl - : private IDEAliasAwareDefaultFlowFunctionsImpl { + : private IDENoAliasDefaultFlowFunctionsImpl { public: - using typename IDEAliasAwareDefaultFlowFunctionsImpl::d_t; - using typename IDEAliasAwareDefaultFlowFunctionsImpl::f_t; - using typename IDEAliasAwareDefaultFlowFunctionsImpl::FlowFunctionPtrType; - using typename IDEAliasAwareDefaultFlowFunctionsImpl::FlowFunctionType; - using typename IDEAliasAwareDefaultFlowFunctionsImpl::n_t; + using typename IDENoAliasDefaultFlowFunctionsImpl::d_t; + using typename IDENoAliasDefaultFlowFunctionsImpl::f_t; + using typename IDENoAliasDefaultFlowFunctionsImpl::FlowFunctionPtrType; + using typename IDENoAliasDefaultFlowFunctionsImpl::FlowFunctionType; + using typename IDENoAliasDefaultFlowFunctionsImpl::n_t; - using IDEAliasAwareDefaultFlowFunctionsImpl::isFunctionModeled; + using IDENoAliasDefaultFlowFunctionsImpl::isFunctionModeled; [[nodiscard]] constexpr LLVMAliasInfoRef getAliasInfo() const noexcept { return AS; @@ -31,7 +31,7 @@ class IDEReachableAllocationSitesDefaultFlowFunctionsImpl constexpr IDEReachableAllocationSitesDefaultFlowFunctionsImpl( LLVMAliasInfoRef AS) noexcept - : IDEAliasAwareDefaultFlowFunctionsImpl(AS) { + : IDENoAliasDefaultFlowFunctionsImpl(), AS(AS) { assert(AS && "You must provide an alias information handle!"); } @@ -46,6 +46,9 @@ class IDEReachableAllocationSitesDefaultFlowFunctionsImpl [[nodiscard]] FlowFunctionPtrType getCallToRetFlowFunctionImpl(n_t CallSite, n_t /*RetSite*/, llvm::ArrayRef /*Callees*/); + +protected: + LLVMAliasInfoRef AS; }; } // namespace detail diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index bcf298e1df..5e66e51f2e 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -1,6 +1,7 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h" +#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Operator.h" @@ -23,16 +24,18 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: container_type Gen; auto AliasSet = - AS.getReachableAllocationSites(Store->getPointerOperand(), Store); + AS.getReachableAllocationSites(Store->getPointerOperand(), true, Store); Gen.insert(AliasSet->begin(), AliasSet->end()); Gen.insert(Store->getValueOperand()); return FFTemplates::lambdaFlow( - [Store, Gen{std::move(Gen)}](d_t Source) -> container_type { + [Store, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { if (Store->getPointerOperand() == Source) { return {}; } - if (Store->getValueOperand() == Source) { + if (Store->getValueOperand() == Source || + AS.isInReachableAllocationSites(Store->getValueOperand(), Source, + true, Store)) { return Gen; } @@ -58,86 +61,49 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: }); } - if (const auto *UnaryOp = llvm::dyn_cast(Curr)) { - container_type Gen; - - auto AliasSet = AS.getReachableAllocationSites(UnaryOp, UnaryOp); - Gen.insert(AliasSet->begin(), AliasSet->end()); - // Gen.insert(UnaryOp->getValueOperand()); - // TODO: this is still the impl from noalias. Use - // getReachableAllocationSites - return FFTemplates::generateFlow(UnaryOp, UnaryOp->getOperand(0)); - } - - if (const auto *BinaryOp = llvm::dyn_cast(Curr)) { - container_type Gen; + return this->IDENoAliasDefaultFlowFunctionsImpl::getNormalFlowFunctionImpl( + Curr, Succ); +} - auto AliasSet = AS.getReachableAllocationSites(BinaryOp, BinaryOp); - Gen.insert(AliasSet->begin(), AliasSet->end()); - // Gen.insert(BinaryOp->getValueOperand()); - // TODO: this is still the impl from noalias. Use - // getReachableAllocationSites - return FFTemplates::generateFlowIf(BinaryOp, [BinaryOp](d_t Source) { - return Source == BinaryOp->getOperand(0) || - Source == BinaryOp->getOperand(1); - }); - } - if (const auto *GetElementPtr = llvm::dyn_cast(Curr)) { - container_type Gen; +auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) + -> FlowFunctionPtrType { - auto AliasSet = AS.getReachableAllocationSites( - GetElementPtr->getPointerOperand(), GetElementPtr); - Gen.insert(AliasSet->begin(), AliasSet->end()); - // Gen.insert(GetElementPtr->getValueOperand()); - // TODO: this is still the impl from noalias. Use - // getReachableAllocationSites - return FFTemplates::generateFlow(GetElementPtr, - GetElementPtr->getPointerOperand()); - } + // TODO: das hab ich mir noch aufgeschrieben, passt aber nicht zu der impl + // hier drunter. - if (const auto *Return = llvm::dyn_cast(Curr)) { - container_type Gen; + // mapfactstocallee + // PropagateArgumentWithSource + // das brauchen wir bei dem call - auto AliasSet = - AS.getReachableAllocationSites(Return->getReturnValue(), Return); - Gen.insert(AliasSet->begin(), AliasSet->end()); + // Meine impl muss höchstwahrscheinlich noch entsprechend angepasst werden. + const auto *Call = llvm::cast(CallInst); - return FFTemplates::lambdaFlow( - [Return, Gen{std::move(Gen)}](d_t Source) -> container_type { - if (Return->getReturnValue() == Source) { - return Gen; - } + std::vector AliasArgs( + Call->arg_size()); - return {Source}; - }); + for (const auto &CurrArg : Call->args()) { + if (llvm::isa(CurrArg)) { + AliasArgs.emplace_back( + AS.getReachableAllocationSites(CurrArg, true, Call)); + continue; + } } - if (const auto *FunctionCall = llvm::dyn_cast(Curr)) { - container_type Gen; - - auto AliasSet = AS.getReachableAllocationSites( - FunctionCall->getReturnedArgOperand(), FunctionCall); - Gen.insert(AliasSet->begin(), AliasSet->end()); + return FFTemplates::lambdaFlow( + [AliasArgs{std::move(AliasArgs)}](d_t Source) -> container_type { + container_type Gen; - return FFTemplates::lambdaFlow( - [FunctionCall, Gen{std::move(Gen)}](d_t Source) -> container_type { - if (FunctionCall->getReturnedArgOperand() == Source) { - return Gen; + for (const auto &CurrArg : AliasArgs) { + if (CurrArg->contains(Source)) { + Gen.insert(CurrArg->begin(), CurrArg->end()); } + } - return {Source}; - }); - } + return Gen; + }); - return this->IDEAliasAwareDefaultFlowFunctionsImpl::getNormalFlowFunctionImpl( - Curr, Succ); -} - -auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: - getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) - -> FlowFunctionPtrType { - // TODO: talk to Fabian about this function. - return this->IDEAliasAwareDefaultFlowFunctionsImpl::getCallFlowFunctionImpl( + return this->IDENoAliasDefaultFlowFunctionsImpl::getCallFlowFunctionImpl( CallInst, CalleeFun); } @@ -171,7 +137,11 @@ static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getRetFlowFunctionImpl(n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, n_t /*RetSite*/) -> FlowFunctionPtrType { - // TODO: talk to Fabian about this function. + // TODO: + // ähnlich zu dem return bei dem aliasreturn problem + // betrifft nur die reachableallocationsites + // prüfen, ob source in den reachableallocationsites drin ist + container_type Gen; if (const auto *Call = llvm::dyn_cast(CallSite)) { @@ -179,6 +149,23 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: populateWithMayAliases(AS, Facts, Call); }; + if (const auto *Return = llvm::dyn_cast(Call)) { + container_type Gen; + + auto AliasSet = + AS.getReachableAllocationSites(Return->getReturnValue(), Return); + Gen.insert(AliasSet->begin(), AliasSet->end()); + + return FFTemplates::lambdaFlow( + [Return, Gen{std::move(Gen)}](d_t Source) -> container_type { + if (Return->getReturnValue() == Source) { + return Gen; + } + + return {Source}; + }); + } + return mapFactsToCaller( Call, ExitInst, [](d_t Param, d_t Source) { @@ -194,8 +181,6 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getCallToRetFlowFunctionImpl(n_t CallSite, n_t RetSite, llvm::ArrayRef Callees) -> FlowFunctionPtrType { - // TODO: talk to Fabian about this function. - return this - ->IDEAliasAwareDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl( - CallSite, RetSite, Callees); + return this->IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl( + CallSite, RetSite, Callees); } diff --git a/test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt b/test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt deleted file mode 100644 index aba3a439d8..0000000000 --- a/test/llvm_test_code/pure_flow/reachable_allocation_sites/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(NoMem2regSources - reachable_allocation_sites_01.cpp - reachable_allocation_sites_02.cpp -) - -foreach(TEST_SRC ${NoMem2regSources}) - generate_ll_file(FILE ${TEST_SRC} DEBUG) -endforeach(TEST_SRC) diff --git a/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp b/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp deleted file mode 100644 index 9a6e0ef087..0000000000 --- a/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_01.cpp +++ /dev/null @@ -1,10 +0,0 @@ -int TestInt = 6; - -int *call2() { return &TestInt; } -int *call1() { return call2(); } - -int main(int /*argc*/, char * /*argv*/[]) { - int *CallReturn = call1(); - - return 0; -} diff --git a/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp b/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp deleted file mode 100644 index a66d480938..0000000000 --- a/test/llvm_test_code/pure_flow/reachable_allocation_sites/reachable_allocation_sites_02.cpp +++ /dev/null @@ -1,13 +0,0 @@ -int TestInt = 6; -int TestInt2 = 12; - -int *call4() { return &TestInt2; } -int *call3() { return &TestInt; } -int call2() { return *call3() + *call4(); } -int call1() { return call2(); } - -int main(int /*argc*/, char * /*argv*/[]) { - int CallReturn = call1(); - - return 0; -} diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index 22dcddff30..ddc4d602c0 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp @@ -1060,133 +1060,6 @@ TEST(PureFlow, CallToRetFlow02) { getCallToRetFlowValueSet(Instr27, RASImpl, Instr27)); } -TEST(PureFlow, ReachableAllocationSites01) { - LLVMProjectIRDB IRDB({unittest::PathToLLTestFiles + - "pure_flow/reachable_allocation_sites/" - "reachable_allocation_sites_01_cpp_dbg.ll"}); - IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); - IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); - IDEReachableAllocationSitesImpl RASImpl = - IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); -#if false - - // ret ptr @TestInt, !dbg !21, !psr.id !22; | ID: 1 - - // %call = call noundef ptr @_Z5call2v(), !dbg !24, !psr.id !25; | ID: 2 - // ret ptr %call, !dbg !26, !psr.id !27; | ID: 3 - - // %call = call noundef ptr @_Z5call1v(), !dbg !50, !psr.id !51; | ID: 14 - // store ptr %call, ptr %CallReturn, align 8, !dbg !48, !psr.id !52; | ID: 15 - - // - const auto *Instr = IRDB.getInstruction(); - ASSERT_TRUE(Instr); - - // EXPECT_EQ(std::set{Instr5}, - // getCallToRetFlowValueSet(Instr10, AliasImpl, Instr5)); - - // store i32 1, ptr %One, align 4, !dbg !255, !psr.id !257; | ID: 22 - const auto *Instr22 = IRDB.getInstruction(22); - ASSERT_TRUE(Instr22); - - // store i32 2, ptr %Two, align 4, !dbg !261, !psr.id !263; | ID: 25 - const auto *Instr25 = IRDB.getInstruction(25); - ASSERT_TRUE(Instr25); - - // ret i32 0, !dbg !266, !psr.id !267; | ID: 27 - const auto *Instr27 = IRDB.getInstruction(27); - ASSERT_TRUE(Instr27); - - EXPECT_EQ(std::set{Instr22}, - getCallToRetFlowValueSet(Instr27, AliasImpl, Instr22)); - EXPECT_EQ(std::set{Instr22}, - getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr22)); - EXPECT_EQ(std::set{Instr22}, - getCallToRetFlowValueSet(Instr27, RASImpl, Instr22)); - - EXPECT_EQ(std::set{Instr25}, - getCallToRetFlowValueSet(Instr27, AliasImpl, Instr25)); - EXPECT_EQ(std::set{Instr25}, - getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr25)); - EXPECT_EQ(std::set{Instr25}, - getCallToRetFlowValueSet(Instr27, RASImpl, Instr25)); - - EXPECT_EQ(std::set{Instr27}, - getCallToRetFlowValueSet(Instr27, AliasImpl, Instr27)); - EXPECT_EQ(std::set{Instr27}, - getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr27)); - EXPECT_EQ(std::set{Instr27}, - getCallToRetFlowValueSet(Instr27, RASImpl, Instr27)); -#endif -} - -TEST(PureFlow, ReachableAllocationSites02) { - LLVMProjectIRDB IRDB({unittest::PathToLLTestFiles + - "pure_flow/reachable_allocation_sites/" - "reachable_allocation_sites_02_cpp_dbg.ll"}); - IDEAliasImpl AliasImpl = IDEAliasImpl(&IRDB); - IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); - IDEReachableAllocationSitesImpl RASImpl = - IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); -#if false - - // ret ptr @TestInt2, !dbg !24, !psr.id !25; | ID: 2 - - // ret ptr @TestInt, !dbg !27, !psr.id !28; | ID: 3 - - // %add = add nsw i32 %0, %1, !dbg !40, !psr.id !41; | ID: 8 - // ret i32 %add, !dbg !42, !psr.id !43; | ID: 9 - - // %call = call noundef i32 @_Z5call2v(), !dbg !45, !psr.id !46; | ID: 10 - // ret i32 %call, !dbg !47, !psr.id !48; | ID: 11 - - // %call = call noundef i32 @_Z5call1v(), !dbg !71, !psr.id !72; | ID: 22 - // store i32 %call, ptr %CallReturn, align 4, !dbg !69, !psr.id !73; | ID: 23 - - // - const auto *Instr = IRDB.getInstruction(); - ASSERT_TRUE(Instr); - - // EXPECT_EQ(std::set{Instr5}, - // getCallToRetFlowValueSet(Instr10, AliasImpl, Instr5)); - - // store i32 1, ptr %One, align 4, !dbg !255, !psr.id !257; | ID: 22 - const auto *Instr22 = IRDB.getInstruction(22); - ASSERT_TRUE(Instr22); - - // store i32 2, ptr %Two, align 4, !dbg !261, !psr.id !263; | ID: 25 - const auto *Instr25 = IRDB.getInstruction(25); - ASSERT_TRUE(Instr25); - - // ret i32 0, !dbg !266, !psr.id !267; | ID: 27 - const auto *Instr27 = IRDB.getInstruction(27); - ASSERT_TRUE(Instr27); - - EXPECT_EQ(std::set{Instr22}, - getCallToRetFlowValueSet(Instr27, AliasImpl, Instr22)); - EXPECT_EQ(std::set{Instr22}, - getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr22)); - EXPECT_EQ(std::set{Instr22}, - getCallToRetFlowValueSet(Instr27, RASImpl, Instr22)); - - EXPECT_EQ(std::set{Instr25}, - getCallToRetFlowValueSet(Instr27, AliasImpl, Instr25)); - EXPECT_EQ(std::set{Instr25}, - getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr25)); - EXPECT_EQ(std::set{Instr25}, - getCallToRetFlowValueSet(Instr27, RASImpl, Instr25)); - - EXPECT_EQ(std::set{Instr27}, - getCallToRetFlowValueSet(Instr27, AliasImpl, Instr27)); - EXPECT_EQ(std::set{Instr27}, - getCallToRetFlowValueSet(Instr27, NoAliasImpl, Instr27)); - EXPECT_EQ(std::set{Instr27}, - getCallToRetFlowValueSet(Instr27, RASImpl, Instr27)); -#endif -} - }; // namespace // main function for the test case From fe0bdd99b94e8ccb1b34a807a57debe26e9856b1 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 17 Jun 2025 00:25:16 +0200 Subject: [PATCH 06/11] ret and call flow, tests seq fault --- ...aultReachableAllocationSitesIDEProblem.cpp | 54 ++++++++++--------- .../IfdsIde/DefaultFlowFunctionTest.cpp | 35 +++++++----- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index 5e66e51f2e..737631835f 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -4,7 +4,6 @@ #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/Operator.h" #include "llvm/Support/Casting.h" #include @@ -52,8 +51,11 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: // Gen.insert(Load->getValueOperand()); return FFTemplates::lambdaFlow( - [Load, Gen{std::move(Gen)}](d_t Source) -> container_type { - if (Load->getPointerOperand() == Source) { + [Load, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { + // TODO: Fabian fragen, ob getPointerOperand() hier richtig ist. + if (Load->getPointerOperand() == Source || + AS.isInReachableAllocationSites(Load->getPointerOperand(), Source, + true, Load)) { return Gen; } @@ -76,35 +78,34 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: // PropagateArgumentWithSource // das brauchen wir bei dem call - // Meine impl muss höchstwahrscheinlich noch entsprechend angepasst werden. + // TODO: Fabian fragen, ob diese Impl so passt. const auto *Call = llvm::cast(CallInst); std::vector AliasArgs( Call->arg_size()); for (const auto &CurrArg : Call->args()) { - if (llvm::isa(CurrArg)) { - AliasArgs.emplace_back( - AS.getReachableAllocationSites(CurrArg, true, Call)); - continue; - } + AliasArgs.emplace_back(AS.getReachableAllocationSites(CurrArg, true, Call)); } - return FFTemplates::lambdaFlow( - [AliasArgs{std::move(AliasArgs)}](d_t Source) -> container_type { - container_type Gen; + if (!AliasArgs.empty()) { + return FFTemplates::lambdaFlow( + [AliasArgs{std::move(AliasArgs)}](d_t Source) -> container_type { + container_type Gen; - for (const auto &CurrArg : AliasArgs) { - if (CurrArg->contains(Source)) { - Gen.insert(CurrArg->begin(), CurrArg->end()); + for (const auto &CurrArg : AliasArgs) { + if (CurrArg->contains(Source)) { + Gen.insert(CurrArg->begin(), CurrArg->end()); + } } - } - return Gen; - }); + return Gen; + }); + } - return this->IDENoAliasDefaultFlowFunctionsImpl::getCallFlowFunctionImpl( - CallInst, CalleeFun); + return mapFactsToCallee(Call, CalleeFun, [](d_t Arg, d_t Source) -> bool { + return Arg == Source; + }); } static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, @@ -142,6 +143,8 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: // betrifft nur die reachableallocationsites // prüfen, ob source in den reachableallocationsites drin ist + // TODO: Fabian fragen, ob diese Impl so passt. + container_type Gen; if (const auto *Call = llvm::dyn_cast(CallSite)) { @@ -157,8 +160,10 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: Gen.insert(AliasSet->begin(), AliasSet->end()); return FFTemplates::lambdaFlow( - [Return, Gen{std::move(Gen)}](d_t Source) -> container_type { - if (Return->getReturnValue() == Source) { + [Return, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { + if (Return->getReturnValue() == Source || + AS.isInReachableAllocationSites(Return->getReturnValue(), + Source, true, Return)) { return Gen; } @@ -168,8 +173,9 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: return mapFactsToCaller( Call, ExitInst, - [](d_t Param, d_t Source) { - return Param == Source && Param->getType()->isPointerTy(); + [AS = AS](d_t Param, d_t Source) { + return (Param == Source && Param->getType()->isPointerTy()) || + AS.isInReachableAllocationSites(Param, Source); }, {}, {}, true, true, PostProcessFacts); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index ddc4d602c0..7137fb0db0 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp @@ -82,12 +82,12 @@ std::set getNormalFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { -#if false + // #if false const auto RASNormalFlowFunc = RASImpl.getNormalFlowFunction(Instr, nullptr); const auto RASLLVMValueSet = RASNormalFlowFunc->computeTargets(Arg); return RASLLVMValueSet; -#endif - return {}; + // #endif + // return {}; } std::set @@ -114,13 +114,13 @@ std::set getCallFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Function *CalleeFunc) { -#if false + // #if false const auto RASCallFlowFunc = RASImpl.getCallFlowFunction(Instr, CalleeFunc); std::set RASLLVMValueSet = RASCallFlowFunc->computeTargets(Arg); return RASLLVMValueSet; -#endif - return {}; + // #endif + // return {}; } std::set @@ -147,14 +147,14 @@ std::set getRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Instruction *ExitInst) { -#if false + // #if false const auto RASRetFlowFunc = RASImpl.getRetFlowFunction(Instr, nullptr, ExitInst, nullptr); std::set RASLLVMValueSet = RASRetFlowFunc->computeTargets(Arg); return RASLLVMValueSet; -#endif - return {}; + // #endif + // return {}; } std::set @@ -180,13 +180,13 @@ std::set getCallToRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { -#if false + // #if false const auto RASCallToRetFlowFunc = RASImpl.getCallToRetFlowFunction(Instr, nullptr, {}); const auto RASLLVMValueSet = RASCallToRetFlowFunc->computeTargets(Arg); return RASLLVMValueSet; -#endif - return {}; + // #endif + // return {}; } std::string stringifyValueSet(const std::set &Vals) { @@ -210,6 +210,7 @@ TEST(PureFlow, NormalFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); const auto *MainFunc = IRDB.getFunction("main"); // %0 @@ -309,6 +310,7 @@ TEST(PureFlow, NormalFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); const auto *MainFunc = IRDB.getFunction("main"); ASSERT_TRUE(MainFunc); @@ -373,6 +375,7 @@ TEST(PureFlow, NormalFlow03) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // %One = alloca i32, align 4, !psr.id !222; | ID: 3 const auto *Instr3 = IRDB.getInstruction(3); @@ -478,6 +481,7 @@ TEST(PureFlow, NormalFlow04) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // %Deref1 = alloca i32, align 4, !psr.id !222; | ID: 7 const auto *Instr7 = IRDB.getInstruction(7); @@ -558,6 +562,7 @@ TEST(PureFlow, CallFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // call void @_Z4callii(i32 noundef %2, i32 noundef %3), !dbg !261, !psr.id // !262; | ID: 26 @@ -600,6 +605,7 @@ TEST(PureFlow, CallFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // %One = alloca i32, align 4, !psr.id !251; | ID: 17 const auto *Instr17 = IRDB.getInstruction(17); @@ -705,6 +711,7 @@ TEST(PureFlow, RetFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // %Two = alloca i32, align 4, !psr.id !251; | ID: 20 const auto *UnusedValue = IRDB.getValueFromId(20); @@ -770,6 +777,7 @@ TEST(PureFlow, RetFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // %Two = alloca i32, align 4, !psr.id !268; | ID: 29 const auto *UnusedValue = IRDB.getValueFromId(29); @@ -850,6 +858,7 @@ TEST(PureFlow, RetFlow03) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // %ThreeInCall = alloca i32, align 4, !psr.id !254; | ID: 15 const auto *Instr15 = IRDB.getValueFromId(15); @@ -956,6 +965,7 @@ TEST(PureFlow, CallToRetFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // store i32 0, ptr %Zero, align 4, !dbg !252, !psr.id !254; | ID: 22 const auto *Instr22 = IRDB.getInstruction(22); @@ -999,6 +1009,7 @@ TEST(PureFlow, CallToRetFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); + IRDB.emitPreprocessedIR(llvm::outs()); // store i32 3, ptr %Three, align 4, !dbg !223, !psr.id !225; | ID: 5 const auto *Instr5 = IRDB.getInstruction(5); From 9314d5fca762cdc05ade5d6e9dca7a8b2d17d617 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 17 Jun 2025 08:45:02 +0200 Subject: [PATCH 07/11] fixed seq faults in tests --- ...faultReachableAllocationSitesIDEProblem.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index 737631835f..1c9068cb27 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -46,7 +46,7 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: container_type Gen; auto AliasSet = - AS.getReachableAllocationSites(Load->getPointerOperand(), Load); + AS.getReachableAllocationSites(Load->getPointerOperand(), true, Load); Gen.insert(AliasSet->begin(), AliasSet->end()); // Gen.insert(Load->getValueOperand()); @@ -81,8 +81,14 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: // TODO: Fabian fragen, ob diese Impl so passt. const auto *Call = llvm::cast(CallInst); - std::vector AliasArgs( - Call->arg_size()); + // TODO: Fabian fragen, wie ich hier am Besten vorher dem Vector schon die + // Größe gebe und später dann drüber loope, auch wenn ich nicht alle "Plätze" + // vom Vector setze. + // + // std::vector + // AliasArgs( + // Call->arg_size()); + std::vector AliasArgs; for (const auto &CurrArg : Call->args()) { AliasArgs.emplace_back(AS.getReachableAllocationSites(CurrArg, true, Call)); @@ -112,7 +118,7 @@ static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, const llvm::Instruction *Context) { container_type Tmp = Facts; for (const auto *Fact : Facts) { - auto Aliases = AS.getReachableAllocationSites(Fact, Context); + auto Aliases = AS.getReachableAllocationSites(Fact, true, Context); for (const auto *Alias : *Aliases) { if (const auto *Inst = llvm::dyn_cast(Alias)) { if (Inst->getParent() == Context->getParent() && @@ -155,8 +161,8 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: if (const auto *Return = llvm::dyn_cast(Call)) { container_type Gen; - auto AliasSet = - AS.getReachableAllocationSites(Return->getReturnValue(), Return); + auto AliasSet = AS.getReachableAllocationSites(Return->getReturnValue(), + true, Return); Gen.insert(AliasSet->begin(), AliasSet->end()); return FFTemplates::lambdaFlow( From ff89b22b6f011fc808582e6430e111736f2a00fa Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 17 Jun 2025 11:11:19 +0200 Subject: [PATCH 08/11] fixed bugs and unittests --- ...aultReachableAllocationSitesIDEProblem.cpp | 115 +++++------------- .../IfdsIde/DefaultFlowFunctionTest.cpp | 35 +----- 2 files changed, 38 insertions(+), 112 deletions(-) diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index 1c9068cb27..51c125236c 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -45,14 +45,12 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: if (const auto *Load = llvm::dyn_cast(Curr)) { container_type Gen; - auto AliasSet = - AS.getReachableAllocationSites(Load->getPointerOperand(), true, Load); + auto AliasSet = AS.getReachableAllocationSites(Load, true, Load); Gen.insert(AliasSet->begin(), AliasSet->end()); - // Gen.insert(Load->getValueOperand()); + Gen.insert(Load); return FFTemplates::lambdaFlow( [Load, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { - // TODO: Fabian fragen, ob getPointerOperand() hier richtig ist. if (Load->getPointerOperand() == Source || AS.isInReachableAllocationSites(Load->getPointerOperand(), Source, true, Load)) { @@ -70,48 +68,32 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) -> FlowFunctionPtrType { - - // TODO: das hab ich mir noch aufgeschrieben, passt aber nicht zu der impl - // hier drunter. - - // mapfactstocallee - // PropagateArgumentWithSource - // das brauchen wir bei dem call - - // TODO: Fabian fragen, ob diese Impl so passt. const auto *Call = llvm::cast(CallInst); - // TODO: Fabian fragen, wie ich hier am Besten vorher dem Vector schon die - // Größe gebe und später dann drüber loope, auch wenn ich nicht alle "Plätze" - // vom Vector setze. - // - // std::vector - // AliasArgs( - // Call->arg_size()); std::vector AliasArgs; + AliasArgs.reserve(Call->arg_size()); for (const auto &CurrArg : Call->args()) { AliasArgs.emplace_back(AS.getReachableAllocationSites(CurrArg, true, Call)); } - if (!AliasArgs.empty()) { - return FFTemplates::lambdaFlow( - [AliasArgs{std::move(AliasArgs)}](d_t Source) -> container_type { - container_type Gen; + return mapFactsToCallee( + Call, CalleeFun, + [Call, AliasArgs = std::move(AliasArgs)](d_t Arg, d_t Source) -> bool { + if (Arg == Source) { + return true; + } - for (const auto &CurrArg : AliasArgs) { - if (CurrArg->contains(Source)) { - Gen.insert(CurrArg->begin(), CurrArg->end()); + if (Arg->getType()->isPointerTy()) { + for (const auto &CurrArg : Call->args()) { + if (Arg == CurrArg) { + return AliasArgs[CurrArg.getOperandNo()]->contains(Source); } } + } - return Gen; - }); - } - - return mapFactsToCallee(Call, CalleeFun, [](d_t Arg, d_t Source) -> bool { - return Arg == Source; - }); + return false; + }); } static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, @@ -128,12 +110,6 @@ static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, } } - if (const auto *Load = llvm::dyn_cast(Alias)) { - // Handle at least one level of indirection... - const auto *PointerOp = Load->getPointerOperand()->stripPointerCasts(); - Tmp.insert(PointerOp); - } - Tmp.insert(Alias); } } @@ -144,49 +120,22 @@ static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getRetFlowFunctionImpl(n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, n_t /*RetSite*/) -> FlowFunctionPtrType { - // TODO: - // ähnlich zu dem return bei dem aliasreturn problem - // betrifft nur die reachableallocationsites - // prüfen, ob source in den reachableallocationsites drin ist - - // TODO: Fabian fragen, ob diese Impl so passt. - - container_type Gen; - - if (const auto *Call = llvm::dyn_cast(CallSite)) { - const auto PostProcessFacts = [AS = AS, Call](container_type &Facts) { - populateWithMayAliases(AS, Facts, Call); - }; - - if (const auto *Return = llvm::dyn_cast(Call)) { - container_type Gen; - - auto AliasSet = AS.getReachableAllocationSites(Return->getReturnValue(), - true, Return); - Gen.insert(AliasSet->begin(), AliasSet->end()); - - return FFTemplates::lambdaFlow( - [Return, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { - if (Return->getReturnValue() == Source || - AS.isInReachableAllocationSites(Return->getReturnValue(), - Source, true, Return)) { - return Gen; - } - - return {Source}; - }); - } - - return mapFactsToCaller( - Call, ExitInst, - [AS = AS](d_t Param, d_t Source) { - return (Param == Source && Param->getType()->isPointerTy()) || - AS.isInReachableAllocationSites(Param, Source); - }, - {}, {}, true, true, PostProcessFacts); - } - - return FFTemplates::killAllFlows(); + const auto *Call = llvm::cast(CallSite); + const auto PostProcessFacts = [AS = AS, Call](container_type &Facts) { + populateWithMayAliases(AS, Facts, Call); + }; + + return mapFactsToCaller( + Call, ExitInst, + [AS = AS](d_t Param, d_t Source) { + return Param->getType()->isPointerTy() && + (Param == Source || + AS.isInReachableAllocationSites(Param, Source)); + }, + [AS = AS](d_t Ret, d_t Source) { + return Ret == Source || AS.isInReachableAllocationSites(Ret, Source); + }, + {}, true, true, PostProcessFacts); } auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index 7137fb0db0..0273985af8 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp @@ -82,12 +82,9 @@ std::set getNormalFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { - // #if false const auto RASNormalFlowFunc = RASImpl.getNormalFlowFunction(Instr, nullptr); const auto RASLLVMValueSet = RASNormalFlowFunc->computeTargets(Arg); return RASLLVMValueSet; - // #endif - // return {}; } std::set @@ -114,13 +111,10 @@ std::set getCallFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Function *CalleeFunc) { - // #if false const auto RASCallFlowFunc = RASImpl.getCallFlowFunction(Instr, CalleeFunc); std::set RASLLVMValueSet = RASCallFlowFunc->computeTargets(Arg); return RASLLVMValueSet; - // #endif - // return {}; } std::set @@ -147,14 +141,11 @@ std::set getRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg, const llvm::Instruction *ExitInst) { - // #if false const auto RASRetFlowFunc = RASImpl.getRetFlowFunction(Instr, nullptr, ExitInst, nullptr); std::set RASLLVMValueSet = RASRetFlowFunc->computeTargets(Arg); return RASLLVMValueSet; - // #endif - // return {}; } std::set @@ -180,13 +171,10 @@ std::set getCallToRetFlowValueSet(const llvm::Instruction *Instr, IDEReachableAllocationSitesImpl &RASImpl, const llvm::Value *Arg) { - // #if false const auto RASCallToRetFlowFunc = RASImpl.getCallToRetFlowFunction(Instr, nullptr, {}); const auto RASLLVMValueSet = RASCallToRetFlowFunc->computeTargets(Arg); return RASLLVMValueSet; - // #endif - // return {}; } std::string stringifyValueSet(const std::set &Vals) { @@ -210,7 +198,6 @@ TEST(PureFlow, NormalFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); const auto *MainFunc = IRDB.getFunction("main"); // %0 @@ -310,7 +297,6 @@ TEST(PureFlow, NormalFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); const auto *MainFunc = IRDB.getFunction("main"); ASSERT_TRUE(MainFunc); @@ -375,7 +361,6 @@ TEST(PureFlow, NormalFlow03) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // %One = alloca i32, align 4, !psr.id !222; | ID: 3 const auto *Instr3 = IRDB.getInstruction(3); @@ -391,7 +376,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr18, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr18}), getNormalFlowValueSet(Instr18, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr3, Instr18}), + EXPECT_EQ((std::set{Instr18}), getNormalFlowValueSet(Instr18, RASImpl, Instr3)); // %3 = load i32, ptr %One, align 4, !dbg !251, !psr.id !252; | ID: 21 const auto *Instr21 = IRDB.getInstruction(21); @@ -400,7 +385,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr21, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr21}), getNormalFlowValueSet(Instr21, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr3, Instr21}), + EXPECT_EQ((std::set{Instr21}), getNormalFlowValueSet(Instr21, RASImpl, Instr3)); // %tobool = icmp ne i32 %3, 0, !dbg !251, !psr.id !253; | ID: 22 @@ -423,7 +408,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr27, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr27}), getNormalFlowValueSet(Instr27, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr3, Instr27}), + EXPECT_EQ((std::set{Instr27}), getNormalFlowValueSet(Instr27, RASImpl, Instr3)); // %5 = load i32, ptr %One, align 4, !dbg !263, !psr.id !264; | ID: 28 @@ -433,7 +418,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr28, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr28}), getNormalFlowValueSet(Instr28, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr3, Instr28}), + EXPECT_EQ((std::set{Instr28}), getNormalFlowValueSet(Instr28, RASImpl, Instr3)); // %add = add nsw i32 %4, %5, !dbg !265, !psr.id !266; | ID: 29 @@ -470,7 +455,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr38, AliasImpl, Instr37)); EXPECT_EQ((std::set{Instr37, Instr38}), getNormalFlowValueSet(Instr38, NoAliasImpl, Instr37)); - EXPECT_EQ((std::set{Instr37, Instr38}), + EXPECT_EQ((std::set{Instr38}), getNormalFlowValueSet(Instr38, RASImpl, Instr37)); } @@ -481,7 +466,6 @@ TEST(PureFlow, NormalFlow04) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // %Deref1 = alloca i32, align 4, !psr.id !222; | ID: 7 const auto *Instr7 = IRDB.getInstruction(7); @@ -562,7 +546,6 @@ TEST(PureFlow, CallFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // call void @_Z4callii(i32 noundef %2, i32 noundef %3), !dbg !261, !psr.id // !262; | ID: 26 @@ -605,7 +588,6 @@ TEST(PureFlow, CallFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // %One = alloca i32, align 4, !psr.id !251; | ID: 17 const auto *Instr17 = IRDB.getInstruction(17); @@ -711,7 +693,6 @@ TEST(PureFlow, RetFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // %Two = alloca i32, align 4, !psr.id !251; | ID: 20 const auto *UnusedValue = IRDB.getValueFromId(20); @@ -777,7 +758,6 @@ TEST(PureFlow, RetFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // %Two = alloca i32, align 4, !psr.id !268; | ID: 29 const auto *UnusedValue = IRDB.getValueFromId(29); @@ -858,7 +838,6 @@ TEST(PureFlow, RetFlow03) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // %ThreeInCall = alloca i32, align 4, !psr.id !254; | ID: 15 const auto *Instr15 = IRDB.getValueFromId(15); @@ -892,7 +871,7 @@ TEST(PureFlow, RetFlow03) { EXPECT_EQ(std::set{Instr29}, getRetFlowValueSet(Instruction30, NoAliasImpl, FunctionZ8newThreePKi->getArg(0), Instruction9)); - EXPECT_EQ(std::set{Instr29}, + EXPECT_EQ((std::set{Instr29, Instr15}), getRetFlowValueSet(Instruction30, RASImpl, FunctionZ8newThreePKi->getArg(0), Instruction9)); @@ -965,7 +944,6 @@ TEST(PureFlow, CallToRetFlow01) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // store i32 0, ptr %Zero, align 4, !dbg !252, !psr.id !254; | ID: 22 const auto *Instr22 = IRDB.getInstruction(22); @@ -1009,7 +987,6 @@ TEST(PureFlow, CallToRetFlow02) { IDENoAliasImpl NoAliasImpl = IDENoAliasImpl(&IRDB); IDEReachableAllocationSitesImpl RASImpl = IDEReachableAllocationSitesImpl(&IRDB); - IRDB.emitPreprocessedIR(llvm::outs()); // store i32 3, ptr %Three, align 4, !dbg !223, !psr.id !225; | ID: 5 const auto *Instr5 = IRDB.getInstruction(5); From 2c9599a1a9e66cb7e5ca69a7aafa4de31e626f59 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 18 Jun 2025 13:08:54 +0200 Subject: [PATCH 09/11] Cleanup + small fixes --- .../IfdsIde/DefaultAliasAwareIDEProblem.h | 30 ++---- .../IfdsIde/DefaultNoAliasIDEProblem.h | 15 --- ...efaultReachableAllocationSitesIDEProblem.h | 28 ++---- .../DefaultAliasAwareIDEFlowFunctions.cpp | 18 +--- ...aultReachableAllocationSitesIDEProblem.cpp | 96 +++++++------------ .../IfdsIde/DefaultFlowFunctionTest.cpp | 12 +-- 6 files changed, 58 insertions(+), 141 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h index eec11ad6da..b139eb980e 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h @@ -38,15 +38,12 @@ class IDEAliasAwareDefaultFlowFunctionsImpl [[nodiscard]] FlowFunctionPtrType getNormalFlowFunctionImpl(n_t Curr, n_t /*Succ*/); - [[nodiscard]] FlowFunctionPtrType getCallFlowFunctionImpl(n_t CallInst, - f_t CalleeFun); [[nodiscard]] FlowFunctionPtrType getRetFlowFunctionImpl(n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, n_t /*RetSite*/); - [[nodiscard]] FlowFunctionPtrType - getCallToRetFlowFunctionImpl(n_t CallSite, n_t /*RetSite*/, - llvm::ArrayRef /*Callees*/); + using IDENoAliasDefaultFlowFunctionsImpl::getCallFlowFunctionImpl; + using IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl; protected: LLVMAliasInfoRef AS; @@ -58,22 +55,7 @@ class DefaultAliasAwareIDEProblem : public IDETabulationProblem, protected detail::IDEAliasAwareDefaultFlowFunctionsImpl { public: - using ProblemAnalysisDomain = AnalysisDomainTy; - using d_t = typename AnalysisDomainTy::d_t; - using n_t = typename AnalysisDomainTy::n_t; - using f_t = typename AnalysisDomainTy::f_t; - using t_t = typename AnalysisDomainTy::t_t; - using v_t = typename AnalysisDomainTy::v_t; - using l_t = typename AnalysisDomainTy::l_t; - using i_t = typename AnalysisDomainTy::i_t; - using db_t = typename AnalysisDomainTy::db_t; - - using ConfigurationTy = HasNoConfigurationType; - - using FlowFunctionType = FlowFunction; - using FlowFunctionPtrType = typename FlowFunctionType::FlowFunctionPtrType; - - using container_type = typename FlowFunctionType::container_type; + using typename IDETabulationProblem::db_t; /// Constructs an IDETabulationProblem with the usual arguments + alias /// information. @@ -86,9 +68,11 @@ class DefaultAliasAwareIDEProblem std::optional ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IDETabulationProblem(IRDB, std::move(EntryPoints), - std::move(ZeroValue)), + ZeroValue), detail::IDEAliasAwareDefaultFlowFunctionsImpl(AS) {} + using detail::IDEAliasAwareDefaultFlowFunctionsImpl::getAliasInfo; + [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override { return getNormalFlowFunctionImpl(Curr, Succ); @@ -129,6 +113,8 @@ class DefaultAliasAwareIFDSProblem : IFDSTabulationProblem(IRDB, std::move(EntryPoints), ZeroValue), detail::IDEAliasAwareDefaultFlowFunctionsImpl(AS) {} + using detail::IDEAliasAwareDefaultFlowFunctionsImpl::getAliasInfo; + [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override { return getNormalFlowFunctionImpl(Curr, Succ); diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h index 1865f749f2..8b99f08f19 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h @@ -48,21 +48,6 @@ class DefaultNoAliasIDEProblem : public IDETabulationProblem, protected detail::IDENoAliasDefaultFlowFunctionsImpl { public: - using ProblemAnalysisDomain = AnalysisDomainTy; - using d_t = typename AnalysisDomainTy::d_t; - using n_t = typename AnalysisDomainTy::n_t; - using f_t = typename AnalysisDomainTy::f_t; - using t_t = typename AnalysisDomainTy::t_t; - using v_t = typename AnalysisDomainTy::v_t; - using l_t = typename AnalysisDomainTy::l_t; - using i_t = typename AnalysisDomainTy::i_t; - using db_t = typename AnalysisDomainTy::db_t; - - using ConfigurationTy = HasNoConfigurationType; - - using FlowFunctionType = FlowFunction; - using FlowFunctionPtrType = typename FlowFunctionType::FlowFunctionPtrType; - using IDETabulationProblem::IDETabulationProblem; [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h index 64948f021b..197be26ee4 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -1,7 +1,7 @@ #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H -#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" // Forward declaration of types for which we only use its pointer or ref type @@ -31,7 +31,7 @@ class IDEReachableAllocationSitesDefaultFlowFunctionsImpl constexpr IDEReachableAllocationSitesDefaultFlowFunctionsImpl( LLVMAliasInfoRef AS) noexcept - : IDENoAliasDefaultFlowFunctionsImpl(), AS(AS) { + : AS(AS) { assert(AS && "You must provide an alias information handle!"); } @@ -43,9 +43,8 @@ class IDEReachableAllocationSitesDefaultFlowFunctionsImpl f_t /*CalleeFun*/, n_t ExitInst, n_t /*RetSite*/); - [[nodiscard]] FlowFunctionPtrType - getCallToRetFlowFunctionImpl(n_t CallSite, n_t /*RetSite*/, - llvm::ArrayRef /*Callees*/); + + using IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl; protected: LLVMAliasInfoRef AS; @@ -57,22 +56,7 @@ class DefaultReachableAllocationSitesIDEProblem : public IDETabulationProblem, protected detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl { public: - using ProblemAnalysisDomain = AnalysisDomainTy; - using d_t = typename AnalysisDomainTy::d_t; - using n_t = typename AnalysisDomainTy::n_t; - using f_t = typename AnalysisDomainTy::f_t; - using t_t = typename AnalysisDomainTy::t_t; - using v_t = typename AnalysisDomainTy::v_t; - using l_t = typename AnalysisDomainTy::l_t; - using i_t = typename AnalysisDomainTy::i_t; - using db_t = typename AnalysisDomainTy::db_t; - - using ConfigurationTy = HasNoConfigurationType; - - using FlowFunctionType = FlowFunction; - using FlowFunctionPtrType = typename FlowFunctionType::FlowFunctionPtrType; - - using container_type = typename FlowFunctionType::container_type; + using typename IDETabulationProblem::db_t; /// Constructs an IDETabulationProblem with the usual arguments + alias /// information. @@ -85,7 +69,7 @@ class DefaultReachableAllocationSitesIDEProblem std::optional ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IDETabulationProblem(IRDB, std::move(EntryPoints), - std::move(ZeroValue)), + ZeroValue), detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl(AS) {} [[nodiscard]] FlowFunctionPtrType getNormalFlowFunction(n_t Curr, diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp index ed18352cee..3f157dfc6d 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp @@ -39,12 +39,6 @@ auto detail::IDEAliasAwareDefaultFlowFunctionsImpl::getNormalFlowFunctionImpl( Curr, Succ); } -auto detail::IDEAliasAwareDefaultFlowFunctionsImpl::getCallFlowFunctionImpl( - n_t CallInst, f_t CalleeFun) -> FlowFunctionPtrType { - return this->IDENoAliasDefaultFlowFunctionsImpl::getCallFlowFunctionImpl( - CallInst, CalleeFun); -} - static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, const llvm::Instruction *Context) { container_type Tmp = Facts; @@ -73,8 +67,8 @@ static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, } auto detail::IDEAliasAwareDefaultFlowFunctionsImpl::getRetFlowFunctionImpl( - n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, n_t /*RetSite*/) - -> FlowFunctionPtrType { + n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, + n_t /*RetSite*/) -> FlowFunctionPtrType { container_type Gen; if (const auto *Call = llvm::dyn_cast(CallSite)) { @@ -92,11 +86,3 @@ auto detail::IDEAliasAwareDefaultFlowFunctionsImpl::getRetFlowFunctionImpl( return FFTemplates::killAllFlows(); } - -auto detail::IDEAliasAwareDefaultFlowFunctionsImpl:: - getCallToRetFlowFunctionImpl(n_t CallSite, n_t RetSite, - llvm::ArrayRef Callees) - -> FlowFunctionPtrType { - return this->IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl( - CallSite, RetSite, Callees); -} diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index 51c125236c..ebcea00336 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -20,12 +20,11 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: getNormalFlowFunctionImpl(n_t Curr, n_t Succ) -> FlowFunctionPtrType { if (const auto *Store = llvm::dyn_cast(Curr)) { - container_type Gen; auto AliasSet = AS.getReachableAllocationSites(Store->getPointerOperand(), true, Store); - Gen.insert(AliasSet->begin(), AliasSet->end()); - Gen.insert(Store->getValueOperand()); + + container_type Gen(AliasSet->begin(), AliasSet->end()); return FFTemplates::lambdaFlow( [Store, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { @@ -35,7 +34,9 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: if (Store->getValueOperand() == Source || AS.isInReachableAllocationSites(Store->getValueOperand(), Source, true, Store)) { - return Gen; + auto Ret = Gen; + Ret.insert(Source); + return Ret; } return {Source}; @@ -43,18 +44,12 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: } if (const auto *Load = llvm::dyn_cast(Curr)) { - container_type Gen; - - auto AliasSet = AS.getReachableAllocationSites(Load, true, Load); - Gen.insert(AliasSet->begin(), AliasSet->end()); - Gen.insert(Load); - return FFTemplates::lambdaFlow( - [Load, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { + [Load, AS = AS](d_t Source) -> container_type { if (Load->getPointerOperand() == Source || AS.isInReachableAllocationSites(Load->getPointerOperand(), Source, true, Load)) { - return Gen; + return {Source, Load}; } return {Source}; @@ -66,55 +61,29 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: } auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: - getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) - -> FlowFunctionPtrType { + getCallFlowFunctionImpl(n_t CallInst, + f_t CalleeFun) -> FlowFunctionPtrType { const auto *Call = llvm::cast(CallInst); - std::vector AliasArgs; - AliasArgs.reserve(Call->arg_size()); - - for (const auto &CurrArg : Call->args()) { - AliasArgs.emplace_back(AS.getReachableAllocationSites(CurrArg, true, Call)); - } - return mapFactsToCallee( - Call, CalleeFun, - [Call, AliasArgs = std::move(AliasArgs)](d_t Arg, d_t Source) -> bool { + Call, CalleeFun, [Call, AS = AS](d_t Arg, d_t Source) -> bool { if (Arg == Source) { return true; } - if (Arg->getType()->isPointerTy()) { - for (const auto &CurrArg : Call->args()) { - if (Arg == CurrArg) { - return AliasArgs[CurrArg.getOperandNo()]->contains(Source); - } - } - } - - return false; + return Arg->getType()->isPointerTy() && + Source->getType()->isPointerTy() && + AS.isInReachableAllocationSites(Arg, Source, true, Call); }); } static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, const llvm::Instruction *Context) { container_type Tmp = Facts; - for (const auto *Fact : Facts) { + for (const auto *Fact : Tmp) { auto Aliases = AS.getReachableAllocationSites(Fact, true, Context); - for (const auto *Alias : *Aliases) { - if (const auto *Inst = llvm::dyn_cast(Alias)) { - if (Inst->getParent() == Context->getParent() && - Context->comesBefore(Inst)) { - // We will see that inst later - continue; - } - } - - Tmp.insert(Alias); - } + Facts.insert(Aliases->begin(), Aliases->end()); } - - Facts = std::move(Tmp); } auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: @@ -127,21 +96,28 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: return mapFactsToCaller( Call, ExitInst, - [AS = AS](d_t Param, d_t Source) { - return Param->getType()->isPointerTy() && - (Param == Source || - AS.isInReachableAllocationSites(Param, Source)); + [AS = AS, ExitInst](d_t Param, d_t Source) { + if (!Param->getType()->isPointerTy()) { + return false; + } + + if (Param == Source) { + return true; + } + + // Arguments are counted as allocation-sites, so we have generated them + // as aliases + return !llvm::isa(Source) && + AS.isInReachableAllocationSites(Param, Source, true, ExitInst); }, - [AS = AS](d_t Ret, d_t Source) { - return Ret == Source || AS.isInReachableAllocationSites(Ret, Source); + [AS = AS, ExitInst](d_t Ret, d_t Source) { + if (Ret == Source) { + return true; + } + + return Ret->getType()->isPointerTy() && + Source->getType()->isPointerTy() && + AS.isInReachableAllocationSites(Ret, Source, true, ExitInst); }, {}, true, true, PostProcessFacts); } - -auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: - getCallToRetFlowFunctionImpl(n_t CallSite, n_t RetSite, - llvm::ArrayRef Callees) - -> FlowFunctionPtrType { - return this->IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl( - CallSite, RetSite, Callees); -} diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index 0273985af8..619617ccd0 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp @@ -376,7 +376,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr18, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr18}), getNormalFlowValueSet(Instr18, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr18}), + EXPECT_EQ((std::set{Instr3, Instr18}), getNormalFlowValueSet(Instr18, RASImpl, Instr3)); // %3 = load i32, ptr %One, align 4, !dbg !251, !psr.id !252; | ID: 21 const auto *Instr21 = IRDB.getInstruction(21); @@ -385,7 +385,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr21, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr21}), getNormalFlowValueSet(Instr21, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr21}), + EXPECT_EQ((std::set{Instr3, Instr21}), getNormalFlowValueSet(Instr21, RASImpl, Instr3)); // %tobool = icmp ne i32 %3, 0, !dbg !251, !psr.id !253; | ID: 22 @@ -408,7 +408,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr27, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr27}), getNormalFlowValueSet(Instr27, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr27}), + EXPECT_EQ((std::set{Instr3, Instr27}), getNormalFlowValueSet(Instr27, RASImpl, Instr3)); // %5 = load i32, ptr %One, align 4, !dbg !263, !psr.id !264; | ID: 28 @@ -418,7 +418,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr28, AliasImpl, Instr3)); EXPECT_EQ((std::set{Instr3, Instr28}), getNormalFlowValueSet(Instr28, NoAliasImpl, Instr3)); - EXPECT_EQ((std::set{Instr28}), + EXPECT_EQ((std::set{Instr3, Instr28}), getNormalFlowValueSet(Instr28, RASImpl, Instr3)); // %add = add nsw i32 %4, %5, !dbg !265, !psr.id !266; | ID: 29 @@ -455,7 +455,7 @@ TEST(PureFlow, NormalFlow03) { getNormalFlowValueSet(Instr38, AliasImpl, Instr37)); EXPECT_EQ((std::set{Instr37, Instr38}), getNormalFlowValueSet(Instr38, NoAliasImpl, Instr37)); - EXPECT_EQ((std::set{Instr38}), + EXPECT_EQ((std::set{Instr37, Instr38}), getNormalFlowValueSet(Instr38, RASImpl, Instr37)); } @@ -871,7 +871,7 @@ TEST(PureFlow, RetFlow03) { EXPECT_EQ(std::set{Instr29}, getRetFlowValueSet(Instruction30, NoAliasImpl, FunctionZ8newThreePKi->getArg(0), Instruction9)); - EXPECT_EQ((std::set{Instr29, Instr15}), + EXPECT_EQ((std::set{Instr29, Instr15, Instruction30}), getRetFlowValueSet(Instruction30, RASImpl, FunctionZ8newThreePKi->getArg(0), Instruction9)); From 39b445da78e6e33d9e20273040666e4bfdebacaa Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 18 Jun 2025 13:11:18 +0200 Subject: [PATCH 10/11] pre-commit --- .../DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp | 4 ++-- .../IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp index 3f157dfc6d..82725b65b1 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp @@ -67,8 +67,8 @@ static void populateWithMayAliases(LLVMAliasInfoRef AS, container_type &Facts, } auto detail::IDEAliasAwareDefaultFlowFunctionsImpl::getRetFlowFunctionImpl( - n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, - n_t /*RetSite*/) -> FlowFunctionPtrType { + n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, n_t /*RetSite*/) + -> FlowFunctionPtrType { container_type Gen; if (const auto *Call = llvm::dyn_cast(CallSite)) { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp index ebcea00336..f76f660ca8 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -61,8 +61,8 @@ auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: } auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: - getCallFlowFunctionImpl(n_t CallInst, - f_t CalleeFun) -> FlowFunctionPtrType { + getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) + -> FlowFunctionPtrType { const auto *Call = llvm::cast(CallInst); return mapFactsToCallee( From b200c8b21d0686f0ef9f362392d2502aa3701e5f Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 18 Jun 2025 13:33:07 +0200 Subject: [PATCH 11/11] Add missing header guards and file headers --- .../DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h | 9 +++++++++ .../DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h | 9 +++++++++ .../DefaultReachableAllocationSitesIDEProblem.h | 9 +++++++++ .../DataFlow/IfdsIde/FunctionDataFlowFacts.h | 13 +++++++++++++ .../DataFlow/IfdsIde/LLVMFunctionDataFlowFacts.h | 14 ++++++++++++++ .../PhasarLLVM/DataFlow/IfdsIde/LibCSummary.h | 14 +++++++++++++- 6 files changed, 67 insertions(+), 1 deletion(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h index b139eb980e..98933d2caf 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h @@ -1,3 +1,12 @@ +/****************************************************************************** + * Copyright (c) 2025 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel, mxHuber and others + *****************************************************************************/ + #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IDEALIASINFOTABULATIONPROBLEM_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IDEALIASINFOTABULATIONPROBLEM_H diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h index 8b99f08f19..3bb35b42ca 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultNoAliasIDEProblem.h @@ -1,3 +1,12 @@ +/****************************************************************************** + * Copyright (c) 2025 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel, mxHuber and others + *****************************************************************************/ + #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IDENOALIASINFOTABULATIONPROBLEM_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IDENOALIASINFOTABULATIONPROBLEM_H diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h index 197be26ee4..eac661ccd4 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -1,3 +1,12 @@ +/****************************************************************************** + * Copyright (c) 2025 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel, mxHuber and others + *****************************************************************************/ + #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_DEFAULTREACHABLEALLOCATIONSITESIDEPROBLEM_H diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/FunctionDataFlowFacts.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/FunctionDataFlowFacts.h index 98cdd56f73..ccb4c6b7c2 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/FunctionDataFlowFacts.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/FunctionDataFlowFacts.h @@ -1,3 +1,14 @@ +/****************************************************************************** + * Copyright (c) 2025 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel, bulletspace and others + *****************************************************************************/ +#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_FUNCTIONDATAFLOWFACTS_H +#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_FUNCTIONDATAFLOWFACTS_H + #include "phasar/Utils/DefaultValue.h" #include "llvm/ADT/StringMap.h" @@ -75,3 +86,5 @@ class FunctionDataFlowFacts { }; } // namespace psr::library_summary + +#endif // PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_FUNCTIONDATAFLOWFACTS_H diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFunctionDataFlowFacts.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFunctionDataFlowFacts.h index 8afba2f715..da04b93b1b 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFunctionDataFlowFacts.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFunctionDataFlowFacts.h @@ -1,3 +1,15 @@ +/****************************************************************************** + * Copyright (c) 2025 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel, bulletspace and others + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_LLVMFUNCTIONDATAFLOWFACTS_H +#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_LLVMFUNCTIONDATAFLOWFACTS_H + #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/FunctionDataFlowFacts.h" #include "phasar/Utils/DefaultValue.h" @@ -73,3 +85,5 @@ class LLVMFunctionDataFlowFacts { std::unordered_map LLVMFdff; }; } // namespace psr::library_summary + +#endif // PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_LLVMFUNCTIONDATAFLOWFACTS_H diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LibCSummary.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LibCSummary.h index cea1c2772c..fdb0c7a164 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LibCSummary.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LibCSummary.h @@ -1,4 +1,14 @@ -#pragma once +/****************************************************************************** + * Copyright (c) 2025 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel, bulletspace and others + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_LIBCSUMMARY_H +#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_LIBCSUMMARY_H namespace psr { namespace library_summary { @@ -7,3 +17,5 @@ class FunctionDataFlowFacts; [[nodiscard]] const library_summary::FunctionDataFlowFacts &getLibCSummary(); } // namespace psr + +#endif // PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_LIBCSUMMARY_H