Skip to content

Commit de7532a

Browse files
authored
Merge pull request #471 from secure-software-engineering/f-LCAImprovements
LCA improvements
2 parents 61a8aad + 23c0d21 commit de7532a

7 files changed

Lines changed: 373 additions & 357 deletions

File tree

include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/EdgeFunctionComposer.h"
2020
#include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/IDETabulationProblem.h"
2121
#include "phasar/PhasarLLVM/Domain/AnalysisDomain.h"
22+
#include "phasar/PhasarLLVM/Utils/LatticeDomain.h"
2223

2324
namespace llvm {
2425
class Instruction;
@@ -31,7 +32,7 @@ namespace psr {
3132

3233
struct IDELinearConstantAnalysisDomain : public LLVMAnalysisDomainDefault {
3334
// int64_t corresponds to llvm's type of constant integer
34-
using l_t = int64_t;
35+
using l_t = LatticeDomain<int64_t>;
3536
};
3637

3738
class LLVMBasedICFG;
@@ -176,10 +177,10 @@ class IDELinearConstantAnalysis
176177
public std::enable_shared_from_this<GenConstant> {
177178
private:
178179
const unsigned GenConstantId;
179-
const l_t IntConst;
180+
const int64_t IntConst;
180181

181182
public:
182-
explicit GenConstant(l_t IntConst);
183+
explicit GenConstant(int64_t IntConst);
183184

184185
l_t computeTarget(l_t Source) override;
185186

@@ -253,7 +254,7 @@ class IDELinearConstantAnalysis
253254
* @param rop right operand
254255
* @return Result of binary operation
255256
*/
256-
static l_t executeBinOperation(unsigned Op, l_t Lop, l_t Rop);
257+
static l_t executeBinOperation(unsigned Op, l_t LVal, l_t RVal);
257258

258259
static char opToChar(unsigned Op);
259260

include/phasar/PhasarLLVM/Utils/LatticeDomain.h

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,27 @@
1010
#ifndef PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H
1111
#define PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H
1212

13-
#include "llvm/Support/ErrorHandling.h"
14-
1513
#include <iostream>
14+
#include <type_traits>
1615
#include <variant>
1716

17+
#include "llvm/Support/ErrorHandling.h"
18+
#include "llvm/Support/raw_ostream.h"
19+
20+
#include "phasar/Utils/TypeTraits.h"
21+
1822
namespace psr {
1923

2024
/// Represents the infimum of the lattice:
2125
/// Top is the greatest element that is less than or equal to all elements of
2226
/// the lattice.
2327
struct Top {};
2428

25-
static inline std::ostream &operator<<(std::ostream &OS,
26-
[[maybe_unused]] const Top &T) {
29+
inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) {
30+
return OS << "Top";
31+
}
32+
33+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Top /*unused*/) {
2734
return OS << "Top";
2835
}
2936

@@ -32,43 +39,96 @@ static inline std::ostream &operator<<(std::ostream &OS,
3239
/// of the lattice.
3340
struct Bottom {};
3441

35-
static inline std::ostream &operator<<(std::ostream &OS,
36-
[[maybe_unused]] const Bottom &B) {
42+
inline std::ostream &operator<<(std::ostream &OS, Bottom /*unused*/) {
3743
return OS << "Bottom";
3844
}
3945

40-
/// A easy shorthand to construct a complete lattice of L.
41-
template <typename L> using LatticeDomain = std::variant<L, Top, Bottom>;
46+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Bottom /*unused*/) {
47+
return OS << "Bottom";
48+
}
4249

50+
/// A easy shorthand to construct a complete lattice of L.
4351
template <typename L>
52+
struct LatticeDomain : public std::variant<Top, L, Bottom> {
53+
using std::variant<Top, L, Bottom>::variant;
54+
55+
[[nodiscard]] inline bool isBottom() const noexcept {
56+
return std::holds_alternative<Bottom>(*this);
57+
}
58+
[[nodiscard]] inline bool isTop() const noexcept {
59+
return std::holds_alternative<Top>(*this);
60+
}
61+
[[nodiscard]] inline L *getValueOrNull() noexcept {
62+
return std::get_if<L>(this);
63+
}
64+
[[nodiscard]] inline const L *getValueOrNull() const noexcept {
65+
return std::get_if<L>(this);
66+
}
67+
};
68+
69+
template <typename L,
70+
typename = std::void_t<decltype(std::declval<std::ostream &>()
71+
<< std::declval<L>())>>
4472
inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain<L> &LD) {
45-
if (auto T = std::get_if<Top>(&LD)) {
46-
return OS << *T;
73+
if (LD.isBottom()) {
74+
return OS << "Bottom";
4775
}
48-
if (auto B = std::get_if<Bottom>(&LD)) {
49-
return OS << *B;
76+
if (LD.isTop()) {
77+
return OS << "Top";
5078
}
51-
return OS << std::get<L>(LD);
79+
80+
const auto *Val = LD.getValueOrNull();
81+
assert(Val && "Only alternative remaining is L");
82+
return OS << *Val;
83+
}
84+
85+
template <typename L,
86+
typename = std::void_t<decltype(std::declval<llvm::raw_ostream &>()
87+
<< std::declval<L>())>>
88+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
89+
const LatticeDomain<L> &LD) {
90+
if (LD.isBottom()) {
91+
return OS << "Bottom";
92+
}
93+
if (LD.isTop()) {
94+
return OS << "Top";
95+
}
96+
97+
const auto *Val = LD.getValueOrNull();
98+
assert(Val && "Only alternative remaining is L");
99+
return OS << *Val;
52100
}
53101

54102
template <typename L>
55103
inline bool operator==(const LatticeDomain<L> &Lhs,
56104
const LatticeDomain<L> &Rhs) {
57-
if (std::holds_alternative<Top>(Lhs) && std::holds_alternative<Top>(Rhs)) {
58-
return true;
105+
if (Lhs.index() != Rhs.index()) {
106+
return false;
59107
}
60-
if (std::holds_alternative<Bottom>(Lhs) &&
61-
std::holds_alternative<Bottom>(Rhs)) {
62-
return true;
108+
if (auto LhsPtr = Lhs.getValueOrNull()) {
109+
/// No need to check whether Lhs is an L; the indices are already the same
110+
return *LhsPtr == *Rhs.getValueOrNull();
63111
}
64-
if (auto *LhsPtr = std::get_if<L>(&Lhs)) {
65-
if (auto *RhsPtr = std::get_if<L>(&Rhs)) {
66-
return *LhsPtr == *RhsPtr;
67-
}
112+
return true;
113+
}
114+
115+
template <
116+
typename L, typename LL,
117+
typename = std::void_t<decltype(std::declval<LL>() == std::declval<L>())>>
118+
inline bool operator==(const LL &Lhs, const LatticeDomain<L> Rhs) {
119+
if (auto RVal = Rhs.getValueOrNull()) {
120+
return Lhs == *RVal;
68121
}
69122
return false;
70123
}
71124

125+
template <
126+
typename L, typename LL,
127+
typename = std::void_t<decltype(std::declval<LL>() == std::declval<L>())>>
128+
inline bool operator==(const LatticeDomain<L> Lhs, const LL &Rhs) {
129+
return Rhs == Lhs;
130+
}
131+
72132
template <typename L>
73133
inline bool operator!=(const LatticeDomain<L> &Lhs,
74134
const LatticeDomain<L> &Rhs) {
@@ -78,26 +138,24 @@ inline bool operator!=(const LatticeDomain<L> &Lhs,
78138
template <typename L>
79139
inline bool operator<(const LatticeDomain<L> &Lhs,
80140
const LatticeDomain<L> &Rhs) {
81-
// Top < (Lhs::L < Rhs::L) < Bottom
82-
if (std::holds_alternative<Top>(Rhs)) {
141+
/// Top < (Lhs::L < Rhs::L) < Bottom
142+
if (Rhs.isTop()) {
83143
return false;
84144
}
85-
if (std::holds_alternative<Top>(Lhs)) {
145+
if (Lhs.isTop()) {
86146
return true;
87147
}
88-
89-
if (auto *LhsPtr = std::get_if<L>(&Lhs)) {
90-
if (auto *RhsPtr = std::get_if<L>(&Rhs)) {
148+
if (auto LhsPtr = Lhs.getValueOrNull()) {
149+
if (auto RhsPtr = Rhs.getValueOrNull()) {
91150
return *LhsPtr < *RhsPtr;
92151
}
93152
}
94-
95-
if (std::holds_alternative<Bottom>(Rhs)) {
96-
return !std::holds_alternative<Bottom>(Lhs);
97-
}
98-
if (std::holds_alternative<Bottom>(Lhs)) {
153+
if (Lhs.isBottom()) {
99154
return false;
100155
}
156+
if (Rhs.isBottom()) {
157+
return true;
158+
}
101159
llvm_unreachable("All comparision cases should be handled above.");
102160
}
103161

include/phasar/Utils/TypeTraits.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <ostream>
1414
#include <tuple>
1515
#include <type_traits>
16+
#include <variant>
1617

1718
#include "llvm/Support/raw_ostream.h"
1819

@@ -109,6 +110,15 @@ constexpr bool is_std_hashable_v = detail::is_std_hashable<T>::value; // NOLINT
109110
template <typename T>
110111
constexpr bool is_llvm_hashable_v = // NOLINT
111112
detail::is_llvm_hashable<T>::value;
113+
114+
template <typename T> struct is_variant : std::false_type {}; // NOLINT
115+
116+
template <typename... Args>
117+
struct is_variant<std::variant<Args...>> : std::true_type {}; // NOLINT
118+
119+
template <typename T>
120+
inline constexpr bool is_variant_v = is_variant<T>::value; // NOLINT
121+
112122
// NOLINTEND(readability-identifier-naming)
113123
} // namespace psr
114124

0 commit comments

Comments
 (0)