diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h index 9a73977f97..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 @@ -38,17 +47,14 @@ 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; -private: +protected: LLVMAliasInfoRef AS; }; } // namespace detail @@ -58,22 +64,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 +77,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 +122,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..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 @@ -48,21 +57,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 new file mode 100644 index 0000000000..eac661ccd4 --- /dev/null +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -0,0 +1,150 @@ +/****************************************************************************** + * 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 + +#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]] constexpr LLVMAliasInfoRef getAliasInfo() const noexcept { + return AS; + } + + constexpr IDEReachableAllocationSitesDefaultFlowFunctionsImpl( + LLVMAliasInfoRef AS) noexcept + : AS(AS) { + assert(AS && "You must provide an alias information handle!"); + } + + [[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*/); + + using IDENoAliasDefaultFlowFunctionsImpl::getCallToRetFlowFunctionImpl; + +protected: + LLVMAliasInfoRef AS; +}; +} // namespace detail + +template +class DefaultReachableAllocationSitesIDEProblem + : public IDETabulationProblem, + protected detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl { +public: + using typename IDETabulationProblem::db_t; + + /// 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, LLVMAliasInfoRef AS, + std::vector EntryPoints, + std::optional + ZeroValue) noexcept(std::is_nothrow_move_constructible_v) + : IDETabulationProblem(IRDB, std::move(EntryPoints), + ZeroValue), + detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl(AS) {} + + [[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: + /// 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 { + 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/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 diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEFlowFunctions.cpp index ed18352cee..82725b65b1 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; @@ -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 new file mode 100644 index 0000000000..f76f660ca8 --- /dev/null +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.cpp @@ -0,0 +1,123 @@ +#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/Support/Casting.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 { + + if (const auto *Store = llvm::dyn_cast(Curr)) { + + auto AliasSet = + AS.getReachableAllocationSites(Store->getPointerOperand(), true, Store); + + container_type Gen(AliasSet->begin(), AliasSet->end()); + + return FFTemplates::lambdaFlow( + [Store, Gen{std::move(Gen)}, AS = AS](d_t Source) -> container_type { + if (Store->getPointerOperand() == Source) { + return {}; + } + if (Store->getValueOperand() == Source || + AS.isInReachableAllocationSites(Store->getValueOperand(), Source, + true, Store)) { + auto Ret = Gen; + Ret.insert(Source); + return Ret; + } + + return {Source}; + }); + } + + if (const auto *Load = llvm::dyn_cast(Curr)) { + return FFTemplates::lambdaFlow( + [Load, AS = AS](d_t Source) -> container_type { + if (Load->getPointerOperand() == Source || + AS.isInReachableAllocationSites(Load->getPointerOperand(), Source, + true, Load)) { + return {Source, Load}; + } + + return {Source}; + }); + } + + return this->IDENoAliasDefaultFlowFunctionsImpl::getNormalFlowFunctionImpl( + Curr, Succ); +} + +auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + getCallFlowFunctionImpl(n_t CallInst, f_t CalleeFun) + -> FlowFunctionPtrType { + const auto *Call = llvm::cast(CallInst); + + return mapFactsToCallee( + Call, CalleeFun, [Call, AS = AS](d_t Arg, d_t Source) -> bool { + if (Arg == Source) { + return true; + } + + 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 : Tmp) { + auto Aliases = AS.getReachableAllocationSites(Fact, true, Context); + Facts.insert(Aliases->begin(), Aliases->end()); + } +} + +auto detail::IDEReachableAllocationSitesDefaultFlowFunctionsImpl:: + getRetFlowFunctionImpl(n_t CallSite, f_t /*CalleeFun*/, n_t ExitInst, + n_t /*RetSite*/) -> FlowFunctionPtrType { + 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, 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, 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); +} diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/DefaultFlowFunctionTest.cpp index 71d12e3129..619617ccd0 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" @@ -24,7 +25,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,13 +38,28 @@ class IDEAliasImpl : public DefaultAliasAwareIFDSProblem { class IDENoAliasImpl : public DefaultNoAliasIFDSProblem { public: IDENoAliasImpl(LLVMProjectIRDB *IRDB) - : DefaultNoAliasIFDSProblem(IRDB, {}, {}){}; + : DefaultNoAliasIFDSProblem(IRDB, {}, {}) {}; [[nodiscard]] InitialSeeds initialSeeds() override { return {}; }; }; +class IDEReachableAllocationSitesImpl + : public DefaultReachableAllocationSitesIFDSProblem { +public: + IDEReachableAllocationSitesImpl(LLVMProjectIRDB *IRDB) + : DefaultReachableAllocationSitesIFDSProblem(IRDB, &PT, {}, {}), + PT(IRDB) {}; + + [[nodiscard]] InitialSeeds initialSeeds() override { + return {}; + }; + +private: + FilteredLLVMAliasSet PT; +}; + std::set getNormalFlowValueSet(const llvm::Instruction *Instr, IDEAliasImpl &AliasImpl, const llvm::Value *Arg) { @@ -62,6 +78,15 @@ getNormalFlowValueSet(const llvm::Instruction *Instr, return NoAliasLLVMValueSet; } +std::set +getNormalFlowValueSet(const llvm::Instruction *Instr, + IDEReachableAllocationSitesImpl &RASImpl, + const llvm::Value *Arg) { + const auto RASNormalFlowFunc = RASImpl.getNormalFlowFunction(Instr, nullptr); + const auto RASLLVMValueSet = RASNormalFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; +} + std::set getCallFlowValueSet(const llvm::Instruction *Instr, IDEAliasImpl &AliasImpl, const llvm::Value *Arg, const llvm::Function *CalleeFunc) { @@ -82,6 +107,16 @@ 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) { + const auto RASCallFlowFunc = RASImpl.getCallFlowFunction(Instr, CalleeFunc); + std::set RASLLVMValueSet = + RASCallFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; +} + std::set getRetFlowValueSet(const llvm::Instruction *Instr, IDEAliasImpl &AliasImpl, const llvm::Value *Arg, const llvm::Instruction *ExitInst) { @@ -102,6 +137,17 @@ 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) { + const auto RASRetFlowFunc = + RASImpl.getRetFlowFunction(Instr, nullptr, ExitInst, nullptr); + std::set RASLLVMValueSet = + RASRetFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; +} + std::set getCallToRetFlowValueSet(const llvm::Instruction *Instr, IDEAliasImpl &AliasImpl, const llvm::Value *Arg) { @@ -121,6 +167,16 @@ getCallToRetFlowValueSet(const llvm::Instruction *Instr, return NoAliasLLVMValueSet; } +std::set +getCallToRetFlowValueSet(const llvm::Instruction *Instr, + IDEReachableAllocationSitesImpl &RASImpl, + const llvm::Value *Arg) { + const auto RASCallToRetFlowFunc = + RASImpl.getCallToRetFlowFunction(Instr, nullptr, {}); + const auto RASLLVMValueSet = RASCallToRetFlowFunc->computeTargets(Arg); + return RASLLVMValueSet; +} + std::string stringifyValueSet(const std::set &Vals) { std::string Ret; llvm::raw_string_ostream ROS(Ret); @@ -140,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 @@ -166,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); @@ -178,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); @@ -190,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); @@ -202,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) { @@ -219,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); @@ -242,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); @@ -254,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) { @@ -271,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); @@ -286,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); @@ -293,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); @@ -304,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); @@ -312,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); @@ -320,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); @@ -328,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 @@ -341,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); @@ -349,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) { @@ -356,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); @@ -383,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); @@ -395,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); @@ -407,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)); } /* @@ -422,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 @@ -446,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(); } @@ -456,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); @@ -508,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, @@ -517,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), @@ -525,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), @@ -533,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)); } /* @@ -544,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); @@ -559,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 @@ -581,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( @@ -589,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) { @@ -596,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); @@ -611,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 @@ -624,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 @@ -646,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( @@ -654,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) { @@ -661,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); @@ -691,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, Instr15, Instruction30}), + 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); @@ -739,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)); } /* @@ -757,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); @@ -774,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) { @@ -792,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); @@ -809,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); @@ -831,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