Skip to content

SVF Pointer Analyses #767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ Checks: '-*,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-c-arrays,
bugprone-*,
-bugprone-easily-swappable-parameters,
modernize-*,
-modernize-use-trailing-return-type,
-modernize-avoid-c-arrays,
performance-*,
clang-analyzer-*
'
Expand Down
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,8 @@ doc/*
log/*
**/*/logs/

# CMake build dir
build/*

# MS VS Code
.vscode/*
.vscode/

# Eclipse
.cproject
Expand Down
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,18 @@ endif()
include(add_llvm)
add_llvm()

# SVF
option(PHASAR_USE_SVF "Use SVF for more options in alias analysis (default is OFF)" OFF)
if(PHASAR_USE_SVF)
find_package(SVF REQUIRED CONFIG)
message(STATUS "Found SVF ${SVF_VERSION}")

if (NOT PHASAR_USE_Z3)
message(WARNING "SVF requires Z3. Set PHASAR_USE_Z3=ON")
set(PHASAR_USE_Z3 ON)
endif()
endif()

# Z3 Solver
if(PHASAR_IN_TREE)
set (PHASAR_USE_Z3 OFF)
Expand Down
2 changes: 2 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@

#cmakedefine PHASAR_HAS_SQLITE

#cmakedefine PHASAR_USE_SVF

#endif /* PHASAR_CONFIG_CONFIG_H */
21 changes: 11 additions & 10 deletions include/phasar/ControlFlow/CFGBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define PHASAR_CONTROLFLOW_CFGBASE_H

#include "phasar/Utils/ByRef.h"
#include "phasar/Utils/CRTPUtils.h"
#include "phasar/Utils/TypeTraits.h"

namespace psr {
Expand All @@ -22,7 +23,12 @@ template <typename T> struct CFGTraits {
// using f_t
};

template <typename Derived> class CFGBase {
template <typename Derived> class CFGBase : public CRTPBase<Derived> {
friend Derived;

protected:
using CRTPBase<Derived>::self;

public:
using n_t = typename CFGTraits<Derived>::n_t;
using f_t = typename CFGTraits<Derived>::f_t;
Expand Down Expand Up @@ -129,19 +135,14 @@ template <typename Derived> class CFGBase {
void print(ByConstRef<f_t> Fun, llvm::raw_ostream &OS) const {
self().printImpl(Fun, OS);
}

protected:
Derived &self() noexcept { return static_cast<Derived &>(*this); }
const Derived &self() const noexcept {
return static_cast<const Derived &>(*this);
}
};

template <typename ICF, typename Domain>
// NOLINTNEXTLINE(readability-identifier-naming)
PSR_CONCEPT is_cfg_v = is_crtp_base_of_v<CFGBase, ICF>
&&std::is_same_v<typename ICF::n_t, typename Domain::n_t>
&&std::is_same_v<typename ICF::f_t, typename Domain::f_t>;
PSR_CONCEPT is_cfg_v =
is_crtp_base_of_v<CFGBase, ICF> &&
std::is_same_v<typename ICF::n_t, typename Domain::n_t> &&
std::is_same_v<typename ICF::f_t, typename Domain::f_t>;

} // namespace psr

Expand Down
11 changes: 5 additions & 6 deletions include/phasar/ControlFlow/CallGraphBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define PHASAR_CONTROLFLOW_CALLGRAPHBASE_H

#include "phasar/Utils/ByRef.h"
#include "phasar/Utils/CRTPUtils.h"
#include "phasar/Utils/TypeTraits.h"

namespace psr {
Expand All @@ -22,7 +23,10 @@ template <typename T> struct CGTraits {
/// Base class of all CallGraph implementations within phasar (currently only
/// CallGraph<N, F>).
/// Only represents the data, not how to create it.
template <typename Derived> class CallGraphBase {
template <typename Derived> class CallGraphBase : public CRTPBase<Derived> {
friend Derived;
using CRTPBase<Derived>::self;

public:
using n_t = typename CGTraits<Derived>::n_t;
using f_t = typename CGTraits<Derived>::f_t;
Expand All @@ -46,11 +50,6 @@ template <typename Derived> class CallGraphBase {
is_iterable_over_v<decltype(self().getCallersOfImpl(Fun)), n_t>);
return self().getCallersOfImpl(Fun);
}

private:
const Derived &self() const noexcept {
return static_cast<const Derived &>(*this);
}
};
} // namespace psr

Expand Down
23 changes: 9 additions & 14 deletions include/phasar/ControlFlow/ICFGBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "phasar/ControlFlow/CFGBase.h"
#include "phasar/ControlFlow/CallGraphBase.h"
#include "phasar/Utils/CRTPUtils.h"
#include "phasar/Utils/TypeTraits.h"

#include "llvm/ADT/StringRef.h"
Expand All @@ -20,16 +21,14 @@
#include <type_traits>

namespace psr {
template <typename Derived> class ICFGBase {
template <typename Derived> class ICFGBase : public CRTPBase<Derived> {
friend Derived;
using CRTPBase<Derived>::self;

public:
using n_t = typename CFGTraits<Derived>::n_t;
using f_t = typename CFGTraits<Derived>::f_t;

ICFGBase() noexcept {
static_assert(is_crtp_base_of_v<CFGBase, Derived>,
"An ICFG must also be a CFG");
}

/// Returns an iterable range of all function definitions or declarations in
/// the ICFG
[[nodiscard]] decltype(auto) getAllFunctions() const {
Expand Down Expand Up @@ -113,20 +112,16 @@ template <typename Derived> class ICFGBase {
[[nodiscard]] size_t getNumCallSites() const noexcept {
return self().getNumCallSitesImpl();
}

private:
const Derived &self() const noexcept {
return static_cast<const Derived &>(*this);
}
};

/// True, iff ICF is a proper instantiation of ICFGBase with n_t and f_t taken
/// from the given analysis-Domain
template <typename ICF, typename Domain>
// NOLINTNEXTLINE(readability-identifier-naming)
PSR_CONCEPT is_icfg_v = is_crtp_base_of_v<ICFGBase, ICF>
&&std::is_same_v<typename ICF::n_t, typename Domain::n_t>
&&std::is_same_v<typename ICF::f_t, typename Domain::f_t>;
PSR_CONCEPT is_icfg_v =
is_crtp_base_of_v<ICFGBase, ICF> &&
std::is_same_v<typename ICF::n_t, typename Domain::n_t> &&
std::is_same_v<typename ICF::f_t, typename Domain::f_t>;

} // namespace psr

Expand Down
1 change: 0 additions & 1 deletion include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ template <> struct CFGTraits<LLVMBasedBackwardCFG> : CFGTraits<LLVMBasedCFG> {};

namespace detail {
template <typename Derived> class LLVMBasedCFGImpl : public CFGBase<Derived> {
friend CFGBase<Derived>;
friend class LLVMBasedBackwardCFG;

public:
Expand Down
2 changes: 1 addition & 1 deletion include/phasar/PhasarLLVM/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#ifndef PHASAR_PHASARLLVM_POINTER_H
#define PHASAR_PHASARLLVM_POINTER_H

#include "phasar/PhasarLLVM/Pointer/AliasAnalysisView.h"
#include "phasar/PhasarLLVM/Pointer/FilteredLLVMAliasSet.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h"
#include "phasar/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.h"
#include "phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h"

#endif // PHASAR_PHASARLLVM_POINTER_H
99 changes: 99 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/AliasAnalysisView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/******************************************************************************
* 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 and others
*****************************************************************************/

#ifndef PHASAR_PHASARLLVM_POINTER_ALIASANALYSISVIEW_H
#define PHASAR_PHASARLLVM_POINTER_ALIASANALYSISVIEW_H

#include "phasar/Pointer/AliasAnalysisType.h"
#include "phasar/Pointer/AliasResult.h"

#include <memory>
#include <type_traits>

namespace llvm {
class Value;
class DataLayout;
class Function;
} // namespace llvm

namespace psr {
class LLVMProjectIRDB;

class FunctionAliasView {
public:
template <typename T>
using AliasCallbackTy = AliasResult (*)(T *, const llvm::Value *,
const llvm::Value *,
const llvm::DataLayout &);

[[nodiscard]] AliasResult alias(const llvm::Value *V, const llvm::Value *Rep,
const llvm::DataLayout &DL) {
return Alias(Context, V, Rep, DL);
}

template <
typename T, typename AliasFn,
typename = std::enable_if_t<std::is_empty_v<AliasFn> &&
std::is_default_constructible_v<AliasFn>>>
constexpr FunctionAliasView(T *Context, AliasFn /*Alias*/) noexcept
: Context(Context), Alias(&callAlias<T, AliasFn>) {}

private:
template <typename T, typename AliasFn>
static AliasResult callAlias(void *Context, const llvm::Value *V1,
const llvm::Value *V2,
const llvm::DataLayout &DL) {
return AliasFn{}(static_cast<T *>(Context), V1, V2, DL);
}

void *Context{};
AliasCallbackTy<void> Alias{};
};

class AliasAnalysisView {
public:
constexpr AliasAnalysisView(AliasAnalysisType PATy) noexcept : PATy(PATy) {}

virtual ~AliasAnalysisView() = default;

[[nodiscard]] FunctionAliasView getAAResults(const llvm::Function *F) {
assert(F != nullptr);
return doGetAAResults(F);
}

void erase(llvm::Function *F) noexcept {
assert(F != nullptr);
doErase(F);
}

void clear() noexcept { doClear(); }

[[nodiscard]] constexpr AliasAnalysisType
getPointerAnalysisType() const noexcept {
return PATy;
};

[[nodiscard]] static std::unique_ptr<AliasAnalysisView>
create(LLVMProjectIRDB &IRDB, bool UseLazyEvaluation, AliasAnalysisType PATy);

private:
static std::unique_ptr<AliasAnalysisView>
createLLVMBasedAnalysis(LLVMProjectIRDB &IRDB, bool UseLazyEvaluation,
AliasAnalysisType PATy);

virtual FunctionAliasView doGetAAResults(const llvm::Function *F) = 0;
virtual void doErase(llvm::Function *F) noexcept = 0;
virtual void doClear() noexcept = 0;

AliasAnalysisType PATy{};
};

} // namespace psr

#endif // PHASAR_PHASARLLVM_POINTER_ALIASANALYSISVIEW_H
8 changes: 4 additions & 4 deletions include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#ifndef PHASAR_PHASARLLVM_POINTER_LLVMALIASSET_H
#define PHASAR_PHASARLLVM_POINTER_LLVMALIASSET_H

#include "phasar/PhasarLLVM/Pointer/AliasAnalysisView.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h"
#include "phasar/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.h"
#include "phasar/Pointer/AliasInfoBase.h"
#include "phasar/Pointer/AliasInfoTraits.h"
#include "phasar/Pointer/AliasResult.h"
Expand Down Expand Up @@ -69,7 +69,7 @@ class LLVMAliasSet : public AnalysisPropertiesMixin<LLVMAliasSet>,
};

[[nodiscard]] inline AliasAnalysisType getAliasAnalysisType() const noexcept {
return PTA.getPointerAnalysisType();
return PTA->getPointerAnalysisType();
};

[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
Expand Down Expand Up @@ -143,12 +143,12 @@ class LLVMAliasSet : public AnalysisPropertiesMixin<LLVMAliasSet>,
const llvm::GlobalObject *VG) const;

/// Utility function used by computeFunctionsAliasSet(...)
void addPointer(llvm::AAResults &AA, const llvm::DataLayout &DL,
void addPointer(FunctionAliasView AA, const llvm::DataLayout &DL,
const llvm::Value *V, std::vector<const llvm::Value *> &Reps);

[[nodiscard]] static BoxedPtr<AliasSetTy> getEmptyAliasSet();

LLVMBasedAliasAnalysis PTA;
std::unique_ptr<AliasAnalysisView> PTA;
llvm::DenseSet<const llvm::Function *> AnalyzedFunctions;

AliasSetOwner<AliasSetTy>::memory_resource_type MRes;
Expand Down
55 changes: 55 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/SVF/SVFPointsToSet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/******************************************************************************
* 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 and others
*****************************************************************************/
#ifndef PHASAR_PHASARLLVM_POINTER_SVF_SVFPOINTSTOSET_H
#define PHASAR_PHASARLLVM_POINTER_SVF_SVFPOINTSTOSET_H

#include "phasar/Config/phasar-config.h"
#include "phasar/Pointer/PointsToInfo.h"

#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/Value.h"

#ifndef PHASAR_USE_SVF
#error \
"Don't include SVFPointsToSet.h when PhASAR is not configured to include SVF. Set the cmake variable PHASAR_USE_SVF and retry."
#endif

namespace psr {
class LLVMProjectIRDB;
class SVFPointsToInfo;

struct SVFPointsToInfoTraits {
using v_t = const llvm::Value *;
using n_t = const llvm::Instruction *;
using o_t = uint32_t;

// TODO: Use a more efficient representation; maybe even one that does not
// require an expensive transformation from SVF::PointsTo
using PointsToSetTy = llvm::SmallDenseSet<o_t>;

// No special pointer type
using PointsToSetPtrTy = PointsToSetTy;
};

using SVFBasedPointsToInfo = PointsToInfo<SVFPointsToInfoTraits>;
using SVFBasedPointsToInfoRef = PointsToInfoRef<SVFPointsToInfoTraits>;

/// Use SVF to perform a VersionedFlowSensitive pointer analysis and return the
/// results compatible to psr::PointsToInfo and psr::PointsToInfoRef
[[nodiscard]] SVFBasedPointsToInfo
createSVFVFSPointsToInfo(LLVMProjectIRDB &IRDB);

/// Use SVF to perform a ContextDDA pointer analysis and return the
/// results compatible to psr::PointsToInfo and psr::PointsToInfoRef
[[nodiscard]] SVFBasedPointsToInfo
createSVFDDAPointsToInfo(LLVMProjectIRDB &IRDB);

} // namespace psr

#endif // PHASAR_PHASARLLVM_POINTER_SVF_SVFPOINTSTOSET_H
Loading
Loading