Skip to content
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
84 changes: 41 additions & 43 deletions include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,49 +69,48 @@ template <typename L> struct ConstantEdgeFunction {

[[nodiscard]] constexpr bool isConstant() const noexcept { return true; }

// -- constant data member
[[nodiscard]] friend constexpr bool
operator==(ConstantEdgeFunction<L> LHS, ConstantEdgeFunction<L> RHS) noexcept
requires CanEfficientlyPassByValue<ConstantEdgeFunction>
{
return LHS.Value == RHS.Value;
}

value_type Value{};
};
[[nodiscard]] friend constexpr bool
operator==(const ConstantEdgeFunction<L> &LHS,
const ConstantEdgeFunction<L> &RHS) noexcept
requires(!CanEfficientlyPassByValue<ConstantEdgeFunction>)
{
return LHS.Value == RHS.Value;
}

template <typename L>
requires CanEfficientlyPassByValue<ConstantEdgeFunction<L>>
[[nodiscard]] constexpr bool operator==(ConstantEdgeFunction<L> LHS,
ConstantEdgeFunction<L> RHS) noexcept {
return LHS.Value == RHS.Value;
}
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const ConstantEdgeFunction &Id) {
OS << "ConstantEF";
if constexpr (is_llvm_printable_v<
typename ConstantEdgeFunction<L>::value_type>) {
OS << '[' << Id.Value << ']';
}
return OS;
}

template <typename L>
requires(!CanEfficientlyPassByValue<ConstantEdgeFunction<L>>)
[[nodiscard]] constexpr bool
operator==(const ConstantEdgeFunction<L> &LHS,
const ConstantEdgeFunction<L> &RHS) noexcept {
return LHS.Value == RHS.Value;
}
[[nodiscard]] friend auto hash_value(const ConstantEdgeFunction &CEF) noexcept
requires(is_std_hashable_v<typename NonTopBotValue<L>::type> ||
is_llvm_hashable_v<typename NonTopBotValue<L>::type>)
{
using value_type = typename ConstantEdgeFunction<L>::value_type;
if constexpr (is_std_hashable_v<value_type>) {
return std::hash<value_type>{}(CEF.Value);
} else {
using llvm::hash_value;
return hash_value(CEF.Value);
}
}

template <typename L>
[[nodiscard]] llvm::raw_ostream &
operator<<(llvm::raw_ostream &OS, ByConstRef<ConstantEdgeFunction<L>> Id) {
OS << "ConstantEF";
if constexpr (is_llvm_printable_v<
typename ConstantEdgeFunction<L>::value_type>) {
OS << '[' << Id.Value << ']';
}
return OS;
}
// -- constant data member

template <typename L>
requires(is_std_hashable_v<typename NonTopBotValue<L>::type> ||
is_llvm_hashable_v<typename NonTopBotValue<L>::type>)
[[nodiscard]] auto hash_value(const ConstantEdgeFunction<L> &CEF) noexcept {
using value_type = typename ConstantEdgeFunction<L>::value_type;
if constexpr (is_std_hashable_v<value_type>) {
return std::hash<value_type>{}(CEF.Value);
} else {
using llvm::hash_value;
return hash_value(CEF.Value);
}
}
value_type Value{};
};

template <typename L> struct AllBottom final {
using l_t = L;
Expand Down Expand Up @@ -295,6 +294,10 @@ template <typename L> struct EdgeFunctionComposer {
return First.depth() + Second.depth();
}

friend auto hash_value(const EdgeFunctionComposer &EFC) noexcept {
return llvm::hash_combine(EFC.First, EFC.Second);
}

// -- data members

EdgeFunction<l_t> First{};
Expand All @@ -303,11 +306,6 @@ template <typename L> struct EdgeFunctionComposer {

static_assert(HasDepth<EdgeFunctionComposer<int>>);

template <typename L>
auto hash_value(const EdgeFunctionComposer<L> &EFC) noexcept {
return llvm::hash_combine(EFC.First, EFC.Second);
}

template <typename L, uint8_t N> struct JoinEdgeFunction {
using l_t = L;
using JLattice = JoinLatticeTraits<L>;
Expand Down
14 changes: 6 additions & 8 deletions include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ class IDESolver
getSolverResults().dumpResults(*ICF, OS);
}

friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const IDESolver &Solver) {
Solver.dumpResults(OS);
return OS;
}

void dumpAllInterPathEdges() {
llvm::outs() << "COMPUTED INTER PATH EDGES" << '\n';
auto Interpe = this->computedInterPathEdges.cellSet();
Expand Down Expand Up @@ -1917,14 +1923,6 @@ class IDESolver
std::map<std::pair<n_t, d_t>, size_t> FSummaryReuse;
};

template <typename AnalysisDomainTy, typename Container>
llvm::raw_ostream &
operator<<(llvm::raw_ostream &OS,
const IDESolver<AnalysisDomainTy, Container> &Solver) {
Solver.dumpResults(OS);
return OS;
}

template <typename Problem, typename ICF>
IDESolver(Problem &, ICF *)
-> IDESolver<typename Problem::ProblemAnalysisDomain,
Expand Down
160 changes: 68 additions & 92 deletions include/phasar/Domain/LatticeDomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@ template <typename L>
struct LatticeDomain : public std::variant<Top, L, Bottom> {
using std::variant<Top, L, Bottom>::variant;

[[nodiscard]] inline bool isBottom() const noexcept {
[[nodiscard]] constexpr bool isBottom() const noexcept {
return std::holds_alternative<Bottom>(*this);
}
[[nodiscard]] inline bool isTop() const noexcept {
[[nodiscard]] constexpr bool isTop() const noexcept {
return std::holds_alternative<Top>(*this);
}

[[nodiscard]] inline L *getValueOrNull() noexcept {
[[nodiscard]] constexpr L *getValueOrNull() noexcept {
return std::get_if<L>(this);
}
[[nodiscard]] inline const L *getValueOrNull() const noexcept {
[[nodiscard]] constexpr const L *getValueOrNull() const noexcept {
return std::get_if<L>(this);
}

Expand All @@ -93,119 +93,95 @@ struct LatticeDomain : public std::variant<Top, L, Bottom> {
return hash_value(std::get<L>(LD));
}

[[nodiscard]] inline L &assertGetValue() noexcept {
[[nodiscard]] constexpr L &assertGetValue() noexcept {
assert(std::holds_alternative<L>(*this));
return std::get<L>(*this);
}
[[nodiscard]] inline const L &assertGetValue() const noexcept {
[[nodiscard]] constexpr const L &assertGetValue() const noexcept {
assert(std::holds_alternative<L>(*this));
return std::get<L>(*this);
}

template <typename TransformFn, typename... ArgsT>
void onValue(TransformFn Transform, ArgsT &&...Args) {
constexpr void onValue(TransformFn Transform, ArgsT &&...Args) {
if (auto *Val = getValueOrNull()) {
std::invoke(std::move(Transform), *Val, PSR_FWD(Args)...);
}
}
};

template <typename L>
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const LatticeDomain<L> &LD) {
if (LD.isBottom()) {
return OS << "Bottom";
}
if (LD.isTop()) {
return OS << "Top";
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const LatticeDomain &LD) {
if (LD.isBottom()) {
return OS << "Bottom";
}
if (LD.isTop()) {
return OS << "Top";
}

const auto *Val = LD.getValueOrNull();
assert(Val && "Only alternative remaining is L");
if constexpr (is_llvm_printable_v<L>) {
return OS << *Val;
} else {
return OS << PrettyPrinter{*Val};
}
}

const auto *Val = LD.getValueOrNull();
assert(Val && "Only alternative remaining is L");
if constexpr (is_llvm_printable_v<L>) {
return OS << *Val;
} else {
return OS << PrettyPrinter{*Val};
friend std::ostream &operator<<(std::ostream &OS, const LatticeDomain &LD) {
llvm::raw_os_ostream ROS(OS);
ROS << LD;
return OS;
}
}

template <typename L>
inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain<L> &LD) {
llvm::raw_os_ostream ROS(OS);
ROS << LD;
return OS;
}
constexpr bool operator==(const LatticeDomain &Rhs) const {
if (this->index() != Rhs.index()) {
return false;
}
if (auto LhsPtr = this->getValueOrNull()) {
/// No need to check whether Rhs is an L; the indices are already the same
return *LhsPtr == *Rhs.getValueOrNull();
}
return true;
}

template <typename L>
inline bool operator==(const LatticeDomain<L> &Lhs,
const LatticeDomain<L> &Rhs) {
if (Lhs.index() != Rhs.index()) {
template <typename LL>
requires AreEqualityComparable<L, LL>
constexpr bool operator==(const LL &Rhs) const {
if (auto LVal = this->getValueOrNull()) {
return *LVal == Rhs;
}
return false;
}
if (auto LhsPtr = Lhs.getValueOrNull()) {
/// No need to check whether Lhs is an L; the indices are already the same
return *LhsPtr == *Rhs.getValueOrNull();
}
return true;
}

template <typename L, typename LL>
requires AreEqualityComparable<LL, L>
inline bool operator==(const LL &Lhs, const LatticeDomain<L> &Rhs) {
if (auto RVal = Rhs.getValueOrNull()) {
return Lhs == *RVal;
constexpr bool operator==(Bottom /*Rhs*/) const noexcept {
return this->isBottom();
}
return false;
}

template <typename L, typename LL>
requires AreEqualityComparable<LL, L>
inline bool operator==(const LatticeDomain<L> &Lhs, const LL &Rhs) {
return Rhs == Lhs;
}

template <typename L>
inline bool operator==(const LatticeDomain<L> &Lhs, Bottom /*Rhs*/) noexcept {
return Lhs.isBottom();
}

template <typename L>
inline bool operator==(const LatticeDomain<L> &Lhs, Top /*Rhs*/) noexcept {
return Lhs.isTop();
}

template <typename L>
inline bool operator==(Bottom /*Lhs*/, const LatticeDomain<L> &Rhs) noexcept {
return Rhs.isBottom();
}

template <typename L>
inline bool operator==(Top /*Lhs*/, const LatticeDomain<L> &Rhs) noexcept {
return Rhs.isTop();
}

template <typename L>
inline bool operator<(const LatticeDomain<L> &Lhs,
const LatticeDomain<L> &Rhs) {
/// Top < (Lhs::L < Rhs::L) < Bottom
if (Rhs.isTop()) {
return false;
constexpr bool operator==(Top /*Rhs*/) const noexcept {
return this->isTop();
}
if (Lhs.isTop()) {
return true;
}
if (auto LhsPtr = Lhs.getValueOrNull()) {
if (auto RhsPtr = Rhs.getValueOrNull()) {
return *LhsPtr < *RhsPtr;

constexpr bool operator<(const LatticeDomain &Rhs) const {
/// Top < (Lhs::L < Rhs::L) < Bottom
if (Rhs.isTop()) {
return false;
}
} else if (Lhs.isBottom()) {
return false;
}
if (Rhs.isBottom()) {
return true;
if (this->isTop()) {
return true;
}
if (auto LhsPtr = this->getValueOrNull()) {
if (auto RhsPtr = Rhs.getValueOrNull()) {
return *LhsPtr < *RhsPtr;
}
} else if (this->isBottom()) {
return false;
}
if (Rhs.isBottom()) {
return true;
}
llvm_unreachable("All comparison cases should be handled above.");
}
llvm_unreachable("All comparison cases should be handled above.");
}
};

template <typename L> struct JoinLatticeTraits<LatticeDomain<L>> {
using l_t = L;
Expand Down Expand Up @@ -242,7 +218,7 @@ template <typename L>
struct NonTopBotValue<LatticeDomain<L>> {
using type = L;

static L unwrap(LatticeDomain<L> Value) noexcept(
constexpr static L unwrap(LatticeDomain<L> Value) noexcept(
std::is_nothrow_move_constructible_v<L>) {
return std::get<L>(std::move(Value));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,20 @@ class IDEIIAFlowFact {
print(OS);
return Ret;
}
};

inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const IDEIIAFlowFact &FlowFact) {
FlowFact.print(OS);
return OS;
}
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const IDEIIAFlowFact &FlowFact) {
FlowFact.print(OS);
return OS;
}

inline std::ostream &operator<<(std::ostream &OS,
const IDEIIAFlowFact &FlowFact) {
llvm::raw_os_ostream Rso(OS);
FlowFact.print(Rso);
return OS;
}
friend std::ostream &operator<<(std::ostream &OS,
const IDEIIAFlowFact &FlowFact) {
llvm::raw_os_ostream Rso(OS);
FlowFact.print(Rso);
return OS;
}
};

} // namespace psr

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ struct GeneralStatistics {
std::string ModuleName{};

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

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const GeneralStatistics &Statistics);
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const GeneralStatistics &Statistics);
};

/**
* This class uses the Module Pass Mechanism of LLVM to compute
Expand Down
Loading
Loading