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

Open
wants to merge 20 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add some documentation about the steps involved in using SVF from PhASAR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should add sth like that

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
112 changes: 112 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/AliasAnalysisView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/******************************************************************************
* 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{};
};

#define PSR_BIND_ALIASVIEW(Ctx, ...) \
::psr::FunctionAliasView { \
(Ctx), [] { \
struct DefaultConstructibleCallable { \
auto operator()(decltype(Ctx) Context, const llvm::Value *V1, \
const llvm::Value *V2, const llvm::DataLayout &DL) { \
return __VA_ARGS__(Context, V1, V2, DL); \
} \
}; \
return DefaultConstructibleCallable{}; \
}() \
}

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
Loading
Loading