Skip to content
Merged
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ add_json_schema_validator()

# TBB
find_package(TBB QUIET) # needed by GCC
set(PHASAR_USE_TBB ${TBB_FOUND})

# Coverage
if (CODE_COVERAGE)
Expand Down
4 changes: 4 additions & 0 deletions Config.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ else()
find_dependency(roaring REQUIRED CONFIG)
endif()

if (@PHASAR_USE_TBB@)
find_dependency(TBB)
endif()

if (PHASAR_USE_Z3)
find_dependency(Z3 REQUIRED)
endif()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,13 @@ int main(int Argc, char **Argv) {
// Walk every function PhASAR's call-graph knows about, and ask it for all
// known callers, writing (and forgetting) each result immediately instead of
// accumulating all of them.
for (const llvm::Function *Fun : ICF.getAllVertexFunctions()) {
ICF.getCallGraph().iterateCallersView([&](const llvm::Function *Fun,
const auto &Callers) {
auto FunName = Fun->getName();
++FnCount;

ResolvedLoc CalleeLoc = resolveLocation(Fun);
for (const auto *CS : ICF.getCallersOf(Fun)) {
for (const auto *CS : Callers) {
ResolvedLoc CallerLoc = resolveLocation(CS);

OS.write_escaped(CS->getFunction()->getName()) << ',' << CallerLoc << ',';
Expand All @@ -137,7 +138,7 @@ int main(int Argc, char **Argv) {
<< ICF.getNumVertexFunctions() << " functions processed so far\n";
}
}
}
});

OS.close();

Expand Down
20 changes: 20 additions & 0 deletions include/phasar/ControlFlow/CallGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
#include "phasar/Utils/StableVector.h"
#include "phasar/Utils/Utilities.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Function.h"

#include <concepts>
#include <functional>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -52,6 +54,24 @@ class CallGraph : public CallGraphBase<CallGraph<N, F>> {
/// Creates a new, empty call-graph
CallGraph() noexcept = default;

auto
iterateCalleesView(std::invocable<n_t, llvm::ArrayRef<f_t>> auto Fn) const {
return psr::foreachInRange(
CalleesAt, [Fn = copyOrRef(Fn)](const auto &Elem) {
const auto &[CS, Callees] = Elem;
return psr::invokeControlFlow(Fn, CS, llvm::ArrayRef<f_t>(*Callees));
});
}

auto
iterateCallersView(std::invocable<f_t, llvm::ArrayRef<n_t>> auto Fn) const {
return psr::foreachInRange(
CallersOf, [Fn = copyOrRef(Fn)](const auto &Elem) {
const auto &[CS, Callers] = Elem;
return psr::invokeControlFlow(Fn, CS, llvm::ArrayRef<n_t>(*Callers));
});
}

/// Deserializes a previously computed call-graph
template <typename FunctionGetter, typename InstructionGetter>
[[nodiscard]] static CallGraph
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ class IterativeIDESolver
for (ByConstRef<d_t> RetFact : RetFacts) {
auto RetFactId = FactCompressor.getOrInsert(RetFact);

auto EF = [&]() mutable {
auto EF = [&] {
if constexpr (ComputeValues) {
auto RetEF = FECache.getReturnEdgeFunction(
Problem, CallSite, Callee, ExitInst, SummaryFact, RetSite,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

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

#include "llvm/ADT/BitVector.h"
Expand Down Expand Up @@ -180,7 +181,7 @@ template <typename N> class PathSensitivityManagerBase {
[[nodiscard]] static graph_type reverseDAG(graph_type &&Dag,
size_t MaxDepth) {
auto Sz = graph_traits_t::size(Dag);
return reverseDAG(std::move(Dag), identity{}, Sz, MaxDepth);
return reverseDAG(std::move(Dag), IdentityFn{}, Sz, MaxDepth);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class FieldStringManager {
}

auto Kills = KillsCompressor[KS];
Kills.insert(Offs);
Kills.insertUnique(Offs);
return KillsCompressor.getOrInsert(std::move(Kills));
}

Expand Down
2 changes: 1 addition & 1 deletion include/phasar/PhasarLLVM/Pointer/LLVMRawAAResults.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace psr {
constexpr std::invocable<ValueId> auto
llvmRawAliasHandler(const ValueCompressor<PAGVariable> &VC,
std::invocable<const llvm::Value *> auto Callback) {
return [&VC, Callback{copyOrRef(Callback)}](ValueId Alias) {
return [&VC, Callback{std::move(Callback)}](ValueId Alias) {
for (auto V : VC.id2vars(Alias)) {
if (const auto *LLVMVar = V.valueOrNull()) [[likely]] {
std::invoke(Callback, LLVMVar);
Expand Down
4 changes: 3 additions & 1 deletion include/phasar/PhasarLLVM/Pointer/LLVMRawAliasSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "phasar/Utils/TypedVector.h"
#include "phasar/Utils/ValueCompressor.h"

#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/TypeName.h"

Expand Down Expand Up @@ -226,7 +227,8 @@ class LLVMRawAliasSet : public LLVMRawAliasSetBase,
if (!Val->getType()->isPointerTy()) {
return false;
}
if (llvm::isa<llvm::AllocaInst, llvm::Argument>(Val)) {
if (llvm::isa<llvm::AllocaInst, llvm::Argument, llvm::GlobalVariable>(
Val)) {
return true;
}
if (const auto *Call = llvm::dyn_cast<llvm::CallBase>(Val)) {
Expand Down
15 changes: 15 additions & 0 deletions include/phasar/PhasarLLVM/TaintConfig/TaintConfigUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ void forallGeneratedFacts(
std::invoke(WithGenFact, CB);
}

if (!Callee) {
return;
}
for (unsigned I = 0, End = Callee->arg_size(); I < End; ++I) {
if (Config.isSource(Callee->getArg(I))) {
std::invoke(WithGenFact, CB->getArgOperand(I));
Expand All @@ -61,6 +64,9 @@ void collectGeneratedFacts(ContainerTy &Dest, const LLVMTaintConfig &Config,
Dest.insert(CB);
}

if (!Callee) {
return;
}
for (unsigned I = 0, End = Callee->arg_size(); I < End; ++I) {
if (Config.isSource(Callee->getArg(I))) {
Dest.insert(CB->getArgOperand(I));
Expand All @@ -80,6 +86,9 @@ void forallLeakedFacts(const LLVMTaintConfig &Config, const llvm::CallBase *CB,
llvm::for_each(llvm::make_filter_range(CBLeaks, LeakIf), WithLeakFact);
}

if (!Callee) {
return;
}
for (unsigned I = 0, End = Callee->arg_size(); I < End; ++I) {
if (Config.isSink(Callee->getArg(I)) &&
std::invoke(LeakIf, CB->getArgOperand(I))) {
Expand All @@ -101,6 +110,9 @@ void collectLeakedFacts(ContainerTy &Dest, const LLVMTaintConfig &Config,
std::inserter(Dest, Dest.end()), LeakIf);
}

if (!Callee) {
return;
}
for (unsigned I = 0, End = Callee->arg_size(); I < End; ++I) {
if (Config.isSink(Callee->getArg(I)) && LeakIf(CB->getArgOperand(I))) {
Dest.insert(CB->getArgOperand(I));
Expand All @@ -122,6 +134,9 @@ template <typename ContainerTy>
void collectSanitizedFacts(ContainerTy &Dest, const LLVMTaintConfig &Config,
const llvm::CallBase *CB,
const llvm::Function *Callee) {
if (!Callee) {
return;
}
for (unsigned I = 0, End = Callee->arg_size(); I < End; ++I) {
if (Config.isSanitizer(Callee->getArg(I))) {
Dest.insert(CB->getArgOperand(I));
Expand Down
4 changes: 4 additions & 0 deletions include/phasar/Utils/LibrarySummary.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ namespace psr {
/// return the same pointer
[[nodiscard]] bool isSingletonReturningFunction(llvm::StringRef FName) noexcept;

/// Checks whether a function with the given (mangled) name may return the
/// block its first argument points to, similar to realloc.
[[nodiscard]] bool isReallocatingFunction(llvm::StringRef FName) noexcept;

} // namespace psr

#endif // PHASAR_UTILS_LIBRARY_SUMMARY_H
26 changes: 13 additions & 13 deletions include/phasar/Utils/SmallArraySet.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class SmallArraySet : private llvm::SmallVector<T, N> {

[[nodiscard]] static SmallArraySet
fromSorted(llvm::SmallVectorImpl<T> &&Vec) {
assert(std::ranges::is_sorted(Vec) && "Vec is not sorted");
assert(std::ranges::is_sorted(Vec, std::less<T>{}) && "Vec is not sorted");
SmallArraySet Ret(std::move(Vec), /*PreSortedAndUniqued=*/std::true_type{});

Ret.base().erase(std::unique(begin(), end()), end());
Expand All @@ -73,8 +73,8 @@ class SmallArraySet : private llvm::SmallVector<T, N> {

[[nodiscard]] static SmallArraySet
fromSortedUniqued(llvm::SmallVectorImpl<T> &&Vec) {
assert(std::ranges::is_sorted(Vec) && "Vec is not sorted");
assert(std::ranges::adjacent_find(Vec) == Vec.end() &&
assert(std::ranges::is_sorted(Vec, std::less<T>{}) && "Vec is not sorted");
assert(std::ranges::adjacent_find(Vec, std::less<T>{}) == Vec.end() &&
"Vec is not uniqued");

SmallArraySet Ret(std::move(Vec), /*PreSortedAndUniqued=*/std::true_type{});
Expand Down Expand Up @@ -114,7 +114,7 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
this->push_back(Val);

if (Size + 1 == LinearThreshold) [[unlikely]] {
std::ranges::sort(base());
std::ranges::sort(base(), std::less<T>{});
}

return true;
Expand Down Expand Up @@ -154,7 +154,7 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
}
if (I == OtherSize) {
if (this->size() == LinearThreshold) [[unlikely]] {
std::ranges::sort(base());
std::ranges::sort(base(), std::less<T>{});
}
return;
}
Expand Down Expand Up @@ -221,8 +221,8 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
SmallArraySet Merged{};
Merged.resize_for_overwrite(std::min(Size, OtherSize));

auto [Unused1, Unused2, LastOut] =
std::ranges::set_intersection(*this, Other, Merged.begin());
auto [Unused1, Unused2, LastOut] = std::ranges::set_intersection(
*this, Other, Merged.begin(), std::less<T>{});
Merged.base().erase(LastOut, Merged.end());
*this = std::move(Merged);
return Size != size();
Expand All @@ -245,8 +245,8 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
SmallArraySet Merged{};
Merged.resize_for_overwrite(std::min(Size, OtherSize));

auto [Unused1, Unused2, LastOut] =
std::ranges::set_intersection(*this, Other, Merged.begin());
auto [Unused1, Unused2, LastOut] = std::ranges::set_intersection(
*this, Other, Merged.begin(), std::less<T>{});
Merged.base().erase(LastOut, Merged.end());
return Merged;
}
Expand All @@ -256,7 +256,7 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
return llvm::is_contained(base(), Val);
}

return std::ranges::binary_search(base(), Val);
return std::ranges::binary_search(base(), Val, std::less<T>{});
}

void sort() {
Expand All @@ -265,7 +265,7 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
return;
}

std::ranges::sort(base());
std::ranges::sort(base(), std::less<T>{});
}

LLVM_ATTRIBUTE_ALWAYS_INLINE auto foreach (
Expand All @@ -278,7 +278,7 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
if constexpr (std::is_trivially_copyable_v<T>) {
T Arr[LinearThreshold]{};
memcpy(&Arr, Set.data(), Set.size_in_bytes());
std::ranges::sort(Arr, Arr + Set.size());
std::ranges::sort(Arr, Arr + Set.size(), std::less<T>{});
return llvm::hash_combine_range(Arr, Arr + Set.size());
} else {
// Some reduction that ignores the order
Expand Down Expand Up @@ -322,7 +322,7 @@ class SmallArraySet : private llvm::SmallVector<T, N> {
: llvm::SmallVector<T, N>(std::move(Elems)) {}

bool insertImpl(ByConstRef<T> Val) {
const auto It = std::ranges::lower_bound(base(), Val);
const auto It = std::ranges::lower_bound(base(), Val, std::less<T>{});
if (It != this->end() && *It == Val) {
return false;
}
Expand Down
7 changes: 4 additions & 3 deletions include/phasar/Utils/StrongTypeDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#define PHASAR_STRONG_TYPEDEF(NAMESPACE, TYPE, NAME, ...) \
namespace NAMESPACE { \
enum class PSR_ENUM_EXTENSIBILITY(open) NAME : TYPE { __VA_ARGS__ }; \
[[nodiscard]] inline auto hash_value(NAME Id) noexcept { \
return llvm::hash_value(TYPE(Id)); \
} \
} \
namespace llvm { \
template <> struct DenseMapInfo<NAMESPACE::NAME> { \
Expand All @@ -36,9 +39,7 @@
? std::numeric_limits<TYPE>::min() + 1 \
: std::numeric_limits<TYPE>::max() - 1); \
} \
static auto getHashValue(QUAL_NAME Id) noexcept { \
return llvm::hash_value(TYPE(Id)); \
} \
static auto getHashValue(QUAL_NAME Id) noexcept { return hash_value(Id); } \
static constexpr bool isEqual(QUAL_NAME Id1, QUAL_NAME Id2) noexcept { \
return Id1 == Id2; \
} \
Expand Down
18 changes: 11 additions & 7 deletions include/phasar/Utils/TypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,29 +241,32 @@ using ElementType = typename detail::ElementType<Container>::type;

struct TrueFn {
template <typename... Args>
[[nodiscard]] bool operator()(const Args &.../*unused*/) const noexcept {
[[nodiscard]] constexpr bool
operator()(const Args &.../*unused*/) const noexcept {
return true;
}
};

struct FalseFn {
template <typename... Args>
[[nodiscard]] bool operator()(const Args &.../*unused*/) const noexcept {
[[nodiscard]] constexpr bool
operator()(const Args &.../*unused*/) const noexcept {
return false;
}
};

/// Delegates to the ctor of T
template <typename T> struct DefaultConstruct {
template <typename... U>
[[nodiscard]] T
operator()(U &&...Val) noexcept(std::is_nothrow_constructible_v<T, U...>) {
[[nodiscard]] constexpr T operator()(U &&...Val) const
noexcept(std::is_nothrow_constructible_v<T, U...>) {
return T(std::forward<U>(Val)...);
}
};

struct IgnoreArgs {
template <typename... U> void operator()(U &&.../*Val*/) noexcept {}
template <typename... U>
constexpr void operator()(U &&.../*Val*/) const noexcept {}
};

template <typename T>
Expand All @@ -289,13 +292,14 @@ template <has_adl_join T>
}

struct IdentityFn {
template <typename T> decltype(auto) operator()(T &&Val) const noexcept {
template <typename T>
constexpr decltype(auto) operator()(T &&Val) const noexcept {
return std::forward<decltype(Val)>(Val);
}
};

template <typename... ArgsT> struct DummyFn {
void operator()(ArgsT... Arg) const noexcept {}
constexpr void operator()(ArgsT... Arg) const noexcept {}
};

/// True if T can be relocated by copying its bytes (e.g. via memcpy) without
Expand Down
2 changes: 1 addition & 1 deletion include/phasar/Utils/Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ template <typename T> constexpr auto copyOrRef(T &Val) noexcept {
}
}

struct identity {
struct [[deprecated("Use IdentityFn from TypeTraits.h instead")]] identity {
template <typename T> decltype(auto) operator()(T &&Val) const noexcept {
return std::forward<T>(Val);
}
Expand Down
Loading
Loading