Skip to content
7 changes: 0 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,6 @@ include(add_nlohmann_json)
add_nlohmann_json()
add_json_schema_validator()

# TBB
find_package(TBB)

# Coverage
if (CODE_COVERAGE)
set(CODE_COVERAGE_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/code-coverage.cmake")
Expand Down Expand Up @@ -428,10 +425,6 @@ target_sources(phasar_interface INTERFACE
BASE_DIRS "${PHASAR_SRC_DIR}/include" "${PHASAR_BINARY_DIR}/include"
FILES ${PHASAR_PUBLIC_HEADERS} "${PHASAR_BINARY_DIR}/include/phasar/Config/phasar-config.h"
)
if (TARGET TBB::tbb)
target_link_libraries(phasar_interface INTERFACE TBB::tbb)
endif()


# Some preprocessor symbols that need to be available in phasar sources, but should not be installed
add_cxx_compile_definitions(PHASAR_SRC_DIR="${CMAKE_SOURCE_DIR}")
Expand Down
13 changes: 5 additions & 8 deletions include/phasar/DataFlow/IfdsIde/Solver/StaticIDESolverConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,11 @@ struct PSR_PREFERRED_NAME(IFDSSolverConfigWithStatsAndGC) WithGCMode : Base {
static constexpr JumpFunctionGCMode EnableJumpFunctionGC = GCMode;
};

template <typename ProblemTy>
struct DefaultIDESolverConfig : IDESolverConfig {};

template <typename ProblemTy>
requires std::is_base_of_v<
IFDSTabulationProblem<typename ProblemTy::ProblemAnalysisDomain>,
ProblemTy>
struct DefaultIDESolverConfig<ProblemTy> : IFDSSolverConfig {};
template <IFDSProblem ProblemTy>
struct DefaultIDESolverConfig : IFDSSolverConfig {};

template <IDEProblem ProblemTy>
struct DefaultIDESolverConfig<ProblemTy> : IDESolverConfig {};

} // namespace psr

Expand Down
11 changes: 7 additions & 4 deletions include/phasar/DataFlow/WPDS/IfdsIdeRuleProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,10 @@ class IfdsIdeRuleProvider {
}
}();
for (const auto &Succ : RetSites) {
const auto FctSucc = factSucc(Succ, Fct);
// Note: No sparsification here, because getPopRules() needs the
// predecessor of Succ
for (const auto &EntrySE : EntrySEs) {
Outs.emplace_back(Fct, FctSucc, EntrySE, W);
Outs.emplace_back(Fct, Succ, EntrySE, W);
}
}
}
Expand Down Expand Up @@ -240,13 +241,15 @@ class IfdsIdeRuleProvider {
return Outs;
}

[[nodiscard]] constexpr auto &problem() const noexcept { return *Problem; }
[[nodiscard]] constexpr auto &problem() const noexcept {
return Problem.ideProblem();
}

private:
[[nodiscard]] auto factSucc(stack_element_type Succ,
ByConstRef<control_location_type> CL) {
if constexpr (has_advanceToNextUser_v<ICFGTy, control_location_type>) {
return ICF->advancetoNextUser(Succ, CL);
return ICF->advanceToNextUser(Succ, CL);
} else {
return Succ;
}
Expand Down
5 changes: 4 additions & 1 deletion include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define PHASAR_PHASARLLVM_CONTROLFLOW_LLVMBASEDCFG_H_

#include "phasar/ControlFlow/CFGBase.h"
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -76,7 +77,9 @@ template <typename Derived> class LLVMBasedCFGImpl : public CFGBase<Derived> {
[[nodiscard]] bool isExitInstImpl(n_t Inst) const noexcept {
return llvm::isa<llvm::ReturnInst>(Inst);
}
[[nodiscard]] bool isStartPointImpl(n_t Inst) const noexcept;
[[nodiscard]] bool isStartPointImpl(n_t Inst) const noexcept {
return isStartInst(Inst);
}
[[nodiscard]] bool isFieldLoadImpl(n_t Inst) const noexcept;
[[nodiscard]] bool isFieldStoreImpl(n_t Inst) const noexcept;
[[nodiscard]] bool isFallThroughSuccessorImpl(n_t Inst,
Expand Down
20 changes: 18 additions & 2 deletions include/phasar/PhasarLLVM/ControlFlow/SparseLLVMControlFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@

#include "phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedCFGProvider.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"

#include "llvm/IR/CFG.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Value.h"

namespace psr {
Expand All @@ -37,12 +41,24 @@ class SparseLLVMControlFlow {
LLVMAliasInfoRef AI);

private:
[[nodiscard]] static bool isNoopIntrinsic(n_t Inst) {
// isAssumeLikeIntrinsic() alone is not enough: llvm.objectsize and
// llvm.ptr_annotation derive their result from a pointer operand
const auto *II = llvm::dyn_cast<llvm::IntrinsicInst>(Inst);
return II && II->isAssumeLikeIntrinsic() && II->getType()->isVoidTy();
}

[[nodiscard]] static bool isExitInst(n_t Inst) {
return llvm::isa<llvm::ReturnInst, llvm::ResumeInst, llvm::UnreachableInst>(
Inst);
}

[[nodiscard]] static n_t advanceToNextUserImpl(n_t Succ, v_t Fact,
LLVMAliasInfoRef AI) {
if (Succ == Fact || !Succ->getPrevNode() || !Succ->getNextNode()) {
if (Succ == Fact || isExitInst(Succ) || isStartInst(Succ)) {
return Succ;
}
if (llvm::isa<llvm::CallBase>(Succ)) {
if (llvm::isa<llvm::CallBase>(Succ) && !isNoopIntrinsic(Succ)) {
if (llvm::isa<llvm::GlobalValue>(Fact)) {
return Succ;
}
Expand Down
25 changes: 16 additions & 9 deletions include/phasar/PhasarLLVM/Pointer/CachedLLVMAliasIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@

#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/Pointer/AliasAnalysisType.h"
#include "phasar/Pointer/AliasInfoBase.h"
#include "phasar/Pointer/AliasInfoTraits.h"
#include "phasar/Pointer/AliasSetOwner.h"
#include "phasar/Utils/AnalysisProperties.h"

#include "llvm/IR/Function.h"

Expand All @@ -31,7 +33,8 @@ struct AliasInfoTraits<CachedLLVMAliasIterator>
/// \note Currently assumes that the underlying alias information is
/// flow-insensitive and the granularity of different alias-information per
/// instruction is actually at function-level
class CachedLLVMAliasIterator {
class CachedLLVMAliasIterator
: public AnalysisPropertiesMixin<CachedLLVMAliasIterator> {
public:
using alias_traits_t = AliasInfoTraits<CachedLLVMAliasIterator>;
using n_t = alias_traits_t::n_t;
Expand All @@ -44,11 +47,12 @@ class CachedLLVMAliasIterator {

// --- API Functions:

[[nodiscard]] inline bool isInterProcedural() const noexcept {
[[nodiscard]] constexpr bool isInterProcedural() const noexcept {
return false; // No idea, so be conservative here
};

[[nodiscard]] AliasAnalysisType getAliasAnalysisType() const noexcept {
[[nodiscard]] constexpr AliasAnalysisType
getAliasAnalysisType() const noexcept {
return AliasAnalysisType::Invalid; // No idea
}

Expand Down Expand Up @@ -83,7 +87,8 @@ class CachedLLVMAliasIterator {

void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const;

[[nodiscard]] AnalysisProperties getAnalysisProperties() const noexcept {
[[nodiscard]] constexpr AnalysisProperties
getAnalysisProperties() const noexcept {
return AnalysisProperties::None;
}

Expand All @@ -98,18 +103,18 @@ class CachedLLVMAliasIterator {
};

struct ReachableAllocationSitesKeyDMI {
inline static ReachableAllocationSitesKey getEmptyKey() noexcept {
static ReachableAllocationSitesKey getEmptyKey() noexcept {
return {{}, llvm::DenseMapInfo<v_t>::getEmptyKey()};
}
inline static ReachableAllocationSitesKey getTombstoneKey() noexcept {
static ReachableAllocationSitesKey getTombstoneKey() noexcept {
return {{}, llvm::DenseMapInfo<v_t>::getTombstoneKey()};
}
inline static auto getHashValue(ReachableAllocationSitesKey Key) noexcept {
static auto getHashValue(ReachableAllocationSitesKey Key) noexcept {
return llvm::hash_combine(Key.FunAndIntraProcOnly.getOpaqueValue(),
Key.Value);
}
inline static bool isEqual(ReachableAllocationSitesKey Key1,
ReachableAllocationSitesKey Key2) noexcept {
static bool isEqual(ReachableAllocationSitesKey Key1,
ReachableAllocationSitesKey Key2) noexcept {
return Key1.FunAndIntraProcOnly == Key2.FunAndIntraProcOnly &&
Key1.Value == Key2.Value;
}
Expand All @@ -124,6 +129,8 @@ class CachedLLVMAliasIterator {
ReachableAllocationSitesKeyDMI>
ReachableAllocationSitesMap;
};

static_assert(IsAliasInfo<CachedLLVMAliasIterator>);
} // namespace psr

#endif // PHASAR_PHASARLLVM_POINTER_CACHEDALIASITERATOR_H
3 changes: 2 additions & 1 deletion include/phasar/PhasarLLVM/Pointer/MemSSAUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ struct MemSSABundle {
/// Returns true if a LiveOnEntry def is reachable (value may come from outside
/// the function). In that case, ReachingDefs may be incompletely populated.
[[nodiscard]] bool collectReachingDefs(
llvm::MemoryAccess *MA, const llvm::MemorySSA &MSSA,
llvm::MemoryAccess *MA, llvm::MemorySSA &MSSA,
const llvm::MemoryLocation &Loc,
llvm::SmallPtrSetImpl<const llvm::StoreInst *> &ReachingDefs,
llvm::SmallPtrSetImpl<llvm::MemoryAccess *> &Visited);

Expand Down
39 changes: 27 additions & 12 deletions include/phasar/PhasarLLVM/Utils/LLVMShorthands.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/GlobalObject.h"
Expand Down Expand Up @@ -66,14 +67,15 @@ class LLVMProjectIRDB;
* @return True, if given LLVM Type is a struct like this %TSi = type <{ i64 }>.
* False, otherwise.
*/
bool isIntegerLikeType(const llvm::Type *T) noexcept;
[[nodiscard]] bool isIntegerLikeType(const llvm::Type *T) noexcept;

/**
* @brief Checks if the given LLVM Value is either a alloca instruction or a
* heap allocation function, e.g. new, new[], malloc, realloc or calloc.
*/
bool isAllocaInstOrHeapAllocaFunction(const llvm::Value *V) noexcept;
bool isHeapAllocatingFunction(const llvm::Function *F) noexcept;
[[nodiscard]] bool
isAllocaInstOrHeapAllocaFunction(const llvm::Value *V) noexcept;
[[nodiscard]] bool isHeapAllocatingFunction(const llvm::Function *F) noexcept;

/// Returns true if the provided function and the function type are both not
/// null and have the same number of parameters and the same return type. If the
Expand Down Expand Up @@ -101,7 +103,8 @@ LLVM_DEPRECATED("With opaque pointers, this function is not very useful. Use "
bool matchesSignature(const llvm::FunctionType *FType1,
const llvm::FunctionType *FType2);

llvm::ModuleSlotTracker &getModuleSlotTrackerFor(const llvm::Value *V);
[[nodiscard]] llvm::ModuleSlotTracker &
getModuleSlotTrackerFor(const llvm::Value *V);

/**
* @brief Returns a string representation of a LLVM Value.
Expand All @@ -119,7 +122,7 @@ llvm::ModuleSlotTracker &getModuleSlotTrackerFor(const llvm::Value *V);
* @brief Same as llvmIRToString() but tries to shorten the
* resulting string
*/
std::string llvmIRToShortString(const llvm::Value *V);
[[nodiscard]] std::string llvmIRToShortString(const llvm::Value *V);

/**
* @brief Returns a string-representation of a LLVM type.
Expand Down Expand Up @@ -230,7 +233,7 @@ const llvm::Instruction *getNthTermInstruction(const llvm::Function *F,
const llvm::StoreInst *getNthStoreInstruction(const llvm::Function *F,
unsigned StoNo);

llvm::SmallVector<const llvm::Instruction *, 2>
[[nodiscard]] llvm::SmallVector<const llvm::Instruction *, 2>
getAllExitPoints(const llvm::Function *F, bool IncludeResume = true);
void appendAllExitPoints(
const llvm::Function *F,
Expand Down Expand Up @@ -273,13 +276,14 @@ std::size_t computeModuleHash(const llvm::Module *M);
* @brief True, iff V is the compiler-generated guard variable for the
* thread-safe initialization of function-local static variables.
*/
bool isGuardVariable(const llvm::Value *V);
[[nodiscard]] bool isGuardVariable(const llvm::Value *V);

/**
* @brief True, iff V is the compiler-generated branch that leads to the lazy
* initialization of a function-local static variable.
*/
bool isStaticVariableLazyInitializationBranch(const llvm::BranchInst *Inst);
[[nodiscard]] bool
isStaticVariableLazyInitializationBranch(const llvm::BranchInst *Inst);

[[nodiscard]] inline bool
definitelyContainsNoPointerFast(const llvm::Type *Ty) noexcept {
Expand Down Expand Up @@ -370,7 +374,7 @@ void forEachPointerOperand(const llvm::Value *V, HandlerT Handler) {
*/
bool isVarAnnotationIntrinsic(const llvm::Function *F);

inline const llvm::Function *getFunction(const llvm::Value *V) {
[[nodiscard]] inline const llvm::Function *getFunction(const llvm::Value *V) {
if (!V) {
return nullptr;
}
Expand All @@ -382,17 +386,28 @@ inline const llvm::Function *getFunction(const llvm::Value *V) {
}
return nullptr;
}
inline const llvm::Function *getFunction(const llvm::Instruction *Inst) {
[[nodiscard]] inline const llvm::Function *
getFunction(const llvm::Instruction *Inst) {
if (!Inst) {
return nullptr;
}

return Inst->getFunction();
}

const llvm::DIType *stripMemberAndTypedef(const llvm::DIType *Ty);
[[nodiscard]] inline bool isStartInst(const llvm::Instruction *Inst) {
return
#if LLVM_VERSION_MAJOR <= 18
!Inst->getPrevNonDebugInstruction()
#else
!Inst->getPrevNode()
#endif
&& llvm::pred_empty(Inst->getParent());
}

[[nodiscard]] const llvm::DIType *stripMemberAndTypedef(const llvm::DIType *Ty);

inline bool isPointerTy(const llvm::DIType *Ty) {
[[nodiscard]] inline bool isPointerTy(const llvm::DIType *Ty) {
if (const auto *DerivedTy =
llvm::dyn_cast<llvm::DIDerivedType>(stripMemberAndTypedef(Ty))) {
return DerivedTy->getTag() == llvm::dwarf::DW_TAG_pointer_type ||
Expand Down
22 changes: 20 additions & 2 deletions include/phasar/Utils/BitSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define PHASAR_UTILS_BITSET_H

#include "phasar/Utils/TypeTraits.h"
#include "phasar/Utils/Utilities.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
Expand All @@ -24,6 +25,7 @@
#include <iterator>
#include <optional>
#include <type_traits>
#include <utility>

namespace psr {

Expand Down Expand Up @@ -99,6 +101,19 @@ class BitSet {
explicit BitSet(size_t InitialCapacity, bool InitialValue)
: Bits(InitialCapacity, InitialValue) {}

// Moved-from llvm::BitVector is not empty. ValueIdMap requires this in its
// dtor.
BitSet(BitSet &&Other) noexcept : Bits(std::exchange(Other.Bits, {})) {}
BitSet &operator=(BitSet &&Other) noexcept {
std::swap(Bits, Other.Bits);
return *this;
}

BitSet(const BitSet &) = default;
BitSet &operator=(const BitSet &) = default;

~BitSet() = default;

void reserve(size_t Cap) {
if (Bits.size() < Cap) {
Bits.resize(Cap);
Expand Down Expand Up @@ -206,7 +221,7 @@ class BitSet {
///
/// This is likely faster than using iterators.
template <std::invocable<IdT> HandlerFn>
void foreach (HandlerFn Handler) const
bool foreach (HandlerFn Handler) const
noexcept(std::is_nothrow_invocable_v<HandlerFn &, IdT>) {
uintptr_t Store{};
auto Words = getWords(Bits, Store);
Expand All @@ -215,11 +230,14 @@ class BitSet {
while (W) {
auto Curr = std::countr_zero(W) + Offset;
W &= W - 1;
std::invoke(Handler, IdT(Curr));
if (!invokeControlFlow(Handler, IdT(Curr))) {
return false;
}
}

Offset += sizeof(W) * CHAR_BIT;
}
return true;
}

/// Same as mergeWith()
Expand Down
Loading
Loading