Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9b6d4cb
iterative Tarjan Algorithm implemenmted
bulletSpace Aug 23, 2024
1cd7a86
SCCGeneric.h finished
bulletSpace Aug 23, 2024
5fdfc56
typeAssignmentGraph ported
bulletSpace Aug 23, 2024
c38244f
SCCGeneric.h, TypeTraits.h and TypeAssignmentGraph.h updated
bulletSpace Aug 28, 2024
ee6d359
updated template types
bulletSpace Sep 1, 2024
62bb414
error corrections
bulletSpace Sep 4, 2024
7bcd34a
minor corrections
bulletSpace Sep 6, 2024
88adccb
SCCGeneric.h corrections
bulletSpace Sep 8, 2024
8ea087d
SCC Tests added and VTACallGraphTest ported
bulletSpace Sep 16, 2024
7706513
AnalysisConfig.h modified
bulletSpace Sep 16, 2024
4d1d4d2
new test case in SCCGenericTest.cpp
bulletSpace Oct 11, 2024
ed59d42
Merge branch 'development' into f-new-features-from-type-2-phasar
fabianbs96 Sep 2, 2025
17e5b7d
Update TAG, SCCs, and AdjacencyList to use TypedVector
fabianbs96 Sep 2, 2025
8fd2524
Update TAG to llvm::DIType instead of llvm::Type + fix VTACallGraphTe…
fabianbs96 Sep 2, 2025
02ffade
Add call-graph tool to generate call-graphs for arbitrary LLVM IR fil…
fabianbs96 Sep 3, 2025
f038eaf
Add resolver-based TAG construction
fabianbs96 Sep 5, 2025
8502dbc
Fix SCCGenericTest
fabianbs96 Sep 5, 2025
2c4e14d
Refine the concepts for GraphTraits + add some comments
fabianbs96 Sep 5, 2025
73cad97
Merge branch 'development' into f-new-features-from-type-2-phasar
fabianbs96 Sep 5, 2025
47d4bbd
Some cleanup
fabianbs96 Sep 5, 2025
0b3cfb0
Merge branch 'development' into f-new-features-from-type-2-phasar
fabianbs96 Sep 9, 2025
1c1fe88
Merge branch 'development' into f-new-features-from-type-2-phasar
fabianbs96 Sep 14, 2025
a344ef2
Add ground-truth to SCCGenericTest + fix error in Compressor introduc…
fabianbs96 Sep 14, 2025
8ae6a14
Some cleanup + some comments
fabianbs96 Sep 14, 2025
a5d334c
Adapt VTACallGraphTest to TestingSrcLocation + measure timing in call…
fabianbs96 Sep 14, 2025
c9c1a4b
Fix AdjacencyList with TypedVector
fabianbs96 Sep 14, 2025
a0be56f
Fix stack-use-after-scope in TypedVector::operator[], materialized in…
fabianbs96 Sep 14, 2025
fe33074
some cleanup
fabianbs96 Sep 23, 2025
79b1870
Replace Tarjan's algorithm with Pearce's algorithm for computing SCCs…
fabianbs96 Oct 2, 2025
9b7bf9e
Also test recursive version of SCC computation
fabianbs96 Oct 2, 2025
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
4 changes: 3 additions & 1 deletion BreakingChanges.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

## development HEAD

*None*
- The `AdjacencyList` struct now now has one more template argument to denote the intege-like `vertex_t` type. It is the second template argument (which previously was the EdgeType). The edge-type is now denoted by the *third* template argument.
- The `AdjacencyList` switches from using `llvm::NoneType` as empty-node marker to `psr::EmptyType` for forward-compatibility with LLVM-16 that removes `llvm::NoneType`.


## v2503

Expand Down
6 changes: 3 additions & 3 deletions cmake/phasar_macros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ function(add_phasar_library name)
set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name})
endfunction(add_phasar_library)

macro(subdirlist result curdir)
function(subdirlist result curdir)
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
set(dirlist "")

Expand All @@ -363,5 +363,5 @@ macro(subdirlist result curdir)
endif()
endforeach()

set(${result} ${dirlist})
endmacro(subdirlist)
set(${result} ${dirlist} PARENT_SCOPE)
endfunction(subdirlist)
1 change: 1 addition & 0 deletions include/phasar/PhasarLLVM/ControlFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
#include "phasar/PhasarLLVM/ControlFlow/Resolver/OTFResolver.h"
#include "phasar/PhasarLLVM/ControlFlow/Resolver/RTAResolver.h"
#include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h"
#include "phasar/PhasarLLVM/ControlFlow/Resolver/VTAResolver.h"

#endif // PHASAR_PHASARLLVM_CONTROLFLOW_H
3 changes: 3 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/EntryFunctionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ getEntryFunctions(const LLVMProjectIRDB &IRDB,
[[nodiscard]] std::vector<llvm::Function *>
getEntryFunctionsMut(LLVMProjectIRDB &IRDB,
llvm::ArrayRef<std::string> EntryPoints);

[[nodiscard]] std::vector<std::string>
getDefaultEntryPoints(const LLVMProjectIRDB &IRDB);
} // namespace psr

#endif // PHASAR_PHASARLLVM_UTILS_ENTRYFUNCTIONUTILS_H
2 changes: 2 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"

#include "nlohmann/json.hpp"

namespace llvm {
class Function;
} // namespace llvm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,66 @@ class DIBasedTypeHierarchy;
class LLVMVFTableProvider;
class Resolver;

/// Constructs a call-graph using the given CGResolver to resolve indirect
/// calls.
///
/// Uses a fixpoint iteration, if
/// `CGResolver.mutatesHelperAnalysisInformation()` returns true and the
/// soundness S is not Soundness::Unsound.
///
/// \param IRDB The IR code where the call-graph should be based on
/// \param CGResolver The resolver to use for resolving indirect calls.
/// \param EntryPoints The functions, where the call-graph construction should
/// start. The resulting call-graph will only contain functions that are
/// (transitively) reachable from the entry-points.
/// \param S The soundness level. May be used to trade soundness for
/// performance.
[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
buildLLVMBasedCallGraph(const LLVMProjectIRDB &IRDB, Resolver &CGResolver,
llvm::ArrayRef<const llvm::Function *> EntryPoints,
DIBasedTypeHierarchy &TH, LLVMVFTableProvider &VTP,
LLVMAliasInfoRef PT = nullptr,
Soundness S = Soundness::Soundy);

/// Constructs a call-graph using the given CGResolver to resolve indirect
/// calls.
///
/// Uses a fixpoint iteration, if
/// `CGResolver.mutatesHelperAnalysisInformation()` returns true and the
/// soundness S is not Soundness::Unsound.
///
/// \param IRDB The IR code where the call-graph should be based on
/// \param CGResolver The resolver to use for resolving indirect calls.
/// \param EntryPoints Names of the functions, where the call-graph construction
/// should start. The resulting call-graph will only contain functions that are
/// (transitively) reachable from the entry-points.
/// \param S The soundness level. May be used to trade soundness for
/// performance.
[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(const LLVMProjectIRDB &IRDB, Resolver &CGResolver,
llvm::ArrayRef<const llvm::Function *> EntryPoints,
llvm::ArrayRef<std::string> EntryPoints,
Soundness S = Soundness::Soundy);

/// Kept for compatibility with LLVMBasedICFG. See the constructor of
/// LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *, CallGraphAnalysisType,
/// llvm::ArrayRef<std::string>, DIBasedTypeHierarchy *, LLVMAliasInfoRef,
/// Soundness, bool) for more information.
[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
llvm::ArrayRef<std::string> EntryPoints,
llvm::ArrayRef<const llvm::Function *> EntryPoints,
DIBasedTypeHierarchy &TH, LLVMVFTableProvider &VTP,
LLVMAliasInfoRef PT = nullptr,
Soundness S = Soundness::Soundy);

/// Kept for compatibility with LLVMBasedICFG. See the constructor of
/// LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *, CallGraphAnalysisType,
/// llvm::ArrayRef<std::string>, DIBasedTypeHierarchy *, LLVMAliasInfoRef,
/// Soundness, bool) for more information.
[[nodiscard]] LLVMBasedCallGraph
buildLLVMBasedCallGraph(const LLVMProjectIRDB &IRDB, Resolver &CGResolver,
buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
llvm::ArrayRef<std::string> EntryPoints,
DIBasedTypeHierarchy &TH, LLVMVFTableProvider &VTP,
LLVMAliasInfoRef PT = nullptr,
Soundness S = Soundness::Soundy);

} // namespace psr

#endif // PHASAR_PHASARLLVM_CONTROLFLOW_LLVMBASEDCALLGRAPHBUILDER_H
8 changes: 5 additions & 3 deletions include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
/// \param EntryPoints The names of the functions to start with when
/// incrementally building up the ICFG. For whole-program analysis of an
/// executable use {"main"}.
/// \param TH The type-hierarchy implementation to use. Will be constructed
/// on-the-fly if nullptr, but required
/// \param TH The type-hierarchy implementation to use. Must be non-null, if
/// the selected call-graph analysis requires type-hierarchy information;
/// currently, this holds for the CHA and RTA algorithms.
/// \param PT The points-to implementation to use. Will be constructed
/// on-the-fly if nullptr, but required
/// on-the-fly if nullptr, but required; currently, this holds for the OTF and
/// VTA algorithms.
/// \param S The soundness level to expect from the analysis. Currently unused
/// \param IncludeGlobals Properly include global constructors/destructors
/// into the ICFG, if true. Requires to generate artificial functions into the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/******************************************************************************
* 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_CONTROLFLOW_RESOLVER_PRECOMPUTEDRESOLVER_H
#define PHASAR_PHASARLLVM_CONTROLFLOW_RESOLVER_PRECOMPUTEDRESOLVER_H

#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraph.h"
#include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h"
#include "phasar/Utils/MaybeUniquePtr.h"

namespace psr {
/// \brief A Resolver that uses a pre-computed call-graph to resolve indirect
/// calls.
///
/// \note We eventually may want the LLVMBasedCallGraph to *be* a Resolver. This
/// requires the concept of resolvers to generalize beyond LLVM. See
/// <https://github.com/fabianbs96/phasar/tree/f-ResolverCombinators> for
/// reference
class PrecomputedResolver : public Resolver {
public:
PrecomputedResolver(const LLVMProjectIRDB *IRDB,
const LLVMVFTableProvider *VTP,
MaybeUniquePtr<const LLVMBasedCallGraph> BaseCG);

[[nodiscard]] bool
mutatesHelperAnalysisInformation() const noexcept override {
return false;
}

void resolveVirtualCall(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite) override {
resolveFunctionPointer(PossibleTargets, CallSite);
}

void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite) override;

[[nodiscard]] std::string str() const override;

private:
MaybeUniquePtr<const LLVMBasedCallGraph> BaseCG;
};
} // namespace psr

#endif
39 changes: 30 additions & 9 deletions include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define PHASAR_PHASARLLVM_CONTROLFLOW_RESOLVER_RESOLVER_H_

#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/Utils/MaybeUniquePtr.h"

#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -121,12 +122,37 @@ class Resolver {
[[nodiscard]] llvm::ArrayRef<const llvm::Function *>
getAddressTakenFunctions();

[[nodiscard]] static std::unique_ptr<Resolver>
using BaseResolverProvider = llvm::function_ref<MaybeUniquePtr<Resolver>(
const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP,
const DIBasedTypeHierarchy *TH, LLVMAliasInfoRef PT)>;

/// Factory function to create a Resolver that can be used to implement the
/// given call-graph analysis type.
///
/// \param Ty Determines the Resolver subclass to instantiate
/// \param IRDB The IR code where the Resolver should be based on. Must not be
/// nullptr.
/// \param VTP A virtual-table-provider that is used to extract C++-VTables
/// from the IR. Must not be nullptr.
/// \param TH The type-hierarchy implementation to use. Must be non-null, if
/// the selected call-graph analysis requires type-hierarchy information;
/// currently, this holds for the CHA and RTA algorithms.
/// \param PT The points-to implementation to use. Will be constructed
/// on-the-fly if nullptr, but required; currently, this holds for the OTF and
/// VTA algorithms.
static std::unique_ptr<Resolver>
create(CallGraphAnalysisType Ty, const LLVMProjectIRDB *IRDB,
const LLVMVFTableProvider *VTP, const DIBasedTypeHierarchy *TH,
LLVMAliasInfoRef PT = nullptr);
LLVMAliasInfoRef PT = nullptr,
BaseResolverProvider GetBaseRes = nullptr);

protected:
virtual void resolveVirtualCall(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite) = 0;

virtual void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite);

const llvm::Function *
getNonPureVirtualVFTEntry(const llvm::DIType *T, unsigned Idx,
const llvm::CallBase *CallSite,
Expand All @@ -137,17 +163,12 @@ class Resolver {
return psr::getNonPureVirtualVFTEntry(T, Idx, CallSite, *VTP, ReceiverType);
}

// ---

const LLVMProjectIRDB *IRDB{};
const LLVMVFTableProvider *VTP{};
std::optional<llvm::SmallVector<const llvm::Function *, 0>>
AddressTakenFunctions{};

protected:
virtual void resolveVirtualCall(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite) = 0;

virtual void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite);
};
} // namespace psr

Expand Down
112 changes: 112 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/Resolver/VTAResolver.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_CONTROLFLOW_RESOLVER_VTARESOLVER_H
#define PHASAR_PHASARLLVM_CONTROLFLOW_RESOLVER_VTARESOLVER_H

#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraph.h"
#include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h"
#include "phasar/PhasarLLVM/ControlFlow/VTA/TypePropagator.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/Utils/Compressor.h"
#include "phasar/Utils/MaybeUniquePtr.h"
#include "phasar/Utils/SCCGeneric.h"

#include "llvm/ADT/STLFunctionalExtras.h"

namespace psr {

class LLVMProjectIRDB;

/// \brief A Resolver that uses a variant of the Variable Type Analysis to
/// resolver indirect calls.
///
/// Uses debug-information to achieve better results with C++ virtual calls.
/// Uses alias-information as fallback mechanism for when types don't help or
/// are not found, e.g., to resolve function-pointer calls.
///
/// Requires a base-call-graph or at least a base-resolver to resolve indirect
/// calls while constructing the type-assignment graph.
class VTAResolver : public Resolver {
public:
struct DefaultReachableFunctions {
void operator()(const LLVMProjectIRDB &IRDB,
llvm::function_ref<void(const llvm::Function *)> WithFun);
};

/// Constructs a VTAResolver with a given pre-computed call-graph and
/// call-back based alias-information (to-be-replaced by AliasIterator once
/// available #783)
///
/// Builds the type-assignment graph and propagates allocated types though
/// it's SCCs.
explicit VTAResolver(const LLVMProjectIRDB *IRDB,
const LLVMVFTableProvider *VTP, vta::AliasInfoTy AS,
MaybeUniquePtr<const LLVMBasedCallGraph> BaseCG);

/// Constructs a VTAResolver with a given pre-computed call-graph and
/// LLVMAliasInfoRef alias-information.
///
/// Builds the type-assignment graph and propagates allocated types though
/// it's SCCs.
explicit VTAResolver(const LLVMProjectIRDB *IRDB,
const LLVMVFTableProvider *VTP, LLVMAliasInfoRef AS,
MaybeUniquePtr<const LLVMBasedCallGraph> BaseCG);

/// Constructs a VTAResolver with a given base-resolver (no base-call-graph)
/// and call-back based alias-information (to-be-replaced by AliasIterator
/// once available #783).
/// Uses the optional parameter ReachableFunctions to consider only a subset
/// of all functions for building the type-assignment graph
///
/// Builds the type-assignment graph and propagates allocated types though
/// it's SCCs.
explicit VTAResolver(
const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP,
vta::AliasInfoTy AS, MaybeUniquePtr<Resolver> BaseRes,
llvm::function_ref<void(const LLVMProjectIRDB &,
llvm::function_ref<void(const llvm::Function *)>)>
ReachableFunctions = DefaultReachableFunctions{});

/// Constructs a VTAResolver with a given base-resolver (no base-call-graph)
/// and LLVMAliasInfoRef alias-information.
/// Uses the optional parameter ReachableFunctions to consider only a subset
/// of all functions for building the type-assignment graph
///
/// Builds the type-assignment graph and propagates allocated types though
/// it's SCCs.
explicit VTAResolver(
const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP,
LLVMAliasInfoRef AS, MaybeUniquePtr<Resolver> BaseRes,
llvm::function_ref<void(const LLVMProjectIRDB &,
llvm::function_ref<void(const llvm::Function *)>)>
ReachableFunctions = DefaultReachableFunctions{});

[[nodiscard]] std::string str() const override;

[[nodiscard]] bool
mutatesHelperAnalysisInformation() const noexcept override {
return false;
}

private:
void resolveVirtualCall(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite) override;

void resolveFunctionPointer(FunctionSetTy &PossibleTargets,
const llvm::CallBase *CallSite) override;

MaybeUniquePtr<Resolver> BaseResolver{};
vta::TypeAssignment TA{};
SCCHolder<vta::TAGNodeId> SCCs{};
Compressor<vta::TAGNode, vta::TAGNodeId> Nodes;
};
} // namespace psr

#endif // PHASAR_PHASARLLVM_CONTROLFLOW_RESOLVER_VTARESOLVER_H
Loading
Loading